home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / SciAn / src / ScianPictures.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  112KB  |  4,814 lines

  1. /*ScianPictures.c
  2.   Eric Pepke
  3.   June 25, 1990
  4.   Code to draw 3-D pictures in scian.
  5. */
  6.  
  7. #include "Scian.h"
  8. #include "ScianTypes.h"
  9. #include "ScianColors.h"
  10. #include "ScianPictures.h"
  11. #include "ScianIDs.h"
  12. #include "ScianErrors.h"
  13. #include "ScianWindows.h"
  14. #include "ScianDatasets.h"
  15. #include "ScianArrays.h"
  16. #include "ScianPreferences.h"
  17. #include "ScianSpaces.h"
  18. #include "ScianVisObjects.h"
  19. #include "ScianPick.h"
  20.  
  21. static void AppendItemToPicture(PicPtr, PicItemPtr);
  22. static PolyPtr ConvertPolyOntoPolys(PolysPtr polys, PolyPtr poly);
  23.  
  24. #define MAXCYLSIDES    512
  25. #define CYLSIDES    16    /*Sides around cylinders, must be 2^n, 4 or more*/
  26. #define MAXSUB        8    /*Maximum number of subdivisions*/
  27. #ifndef SPHERESUB
  28. #define SPHERESUB    2    /*Number of subdivisions of a sphere*/
  29. #endif
  30.  
  31. #ifdef GRAPHICS
  32. Linestyle dashedLine = 0xF0F0;
  33. Linestyle dottedLine = 0xAAAA;
  34. #endif
  35.  
  36. double cefs[MAXSUB];        /*Chord extension factor for each subdivision*/
  37. double cefs_2[MAXSUB];        /*cefs / 2*/
  38.  
  39. ObjPtr picClass = 0;        /*Class for all pictures*/
  40.  
  41. Bool orderReversed = false;    /*True iff polygon order is reversed*/
  42. Bool overrideColor = false;    /*True iff override color*/
  43. int curColorMode;        /*The current color mode, CMODECMAP or CMODERGB*/
  44. int curColorShading;        /*The current color shading*/
  45. int curLightShading;        /*The current light shading*/ 
  46. Bool curIsTransparent;        /*True iff transparent*/
  47.  
  48. long pictureTime = 0;        /*Picture drawing time*/
  49.  
  50. VertexPtr freedVertices = 0;    /*Freed vertices for the picking*/
  51.  
  52. #ifdef GRAPHICS
  53. unsigned short greyPattern[16] = 
  54.     {
  55.         0x5555,
  56.         0xAAAA,
  57.         0x5555,
  58.         0xAAAA,
  59.         0x5555,
  60.         0xAAAA,
  61.         0x5555,
  62.         0xAAAA,
  63.         0x5555,
  64.         0xAAAA,
  65.         0x5555,
  66.         0xAAAA,
  67.         0x5555,
  68.         0xAAAA,
  69.         0x5555,
  70.         0xAAAA
  71.     };
  72.  
  73. unsigned short funkyGreyPattern[16] = 
  74.     {
  75.         0x5555,
  76.         0x5555,
  77.         0xAAAA,
  78.         0xAAAA,
  79.         0x5555,
  80.         0x5555,
  81.         0xAAAA,
  82.         0xAAAA,
  83.         0x5555,
  84.         0x5555,
  85.         0xAAAA,
  86.         0xAAAA,
  87.         0x5555,
  88.         0x5555,
  89.         0xAAAA,
  90.         0xAAAA
  91.     };
  92.  
  93. unsigned short oddPattern[16] = 
  94.     {
  95.         0xFFFF,
  96.         0x0000,
  97.         0xFFFF,
  98.         0x0000,
  99.         0xFFFF,
  100.         0x0000,
  101.         0xFFFF,
  102.         0x0000,
  103.         0xFFFF,
  104.         0x0000,
  105.         0xFFFF,
  106.         0x0000,
  107.         0xFFFF,
  108.         0x0000,
  109.         0xFFFF,
  110.         0x0000
  111.     };
  112.  
  113. unsigned short evenPattern[16] = 
  114.     {
  115.         0x0000,
  116.         0xFFFF,
  117.         0x0000,
  118.         0xFFFF,
  119.         0x0000,
  120.         0xFFFF,
  121.         0x0000,
  122.         0xFFFF,
  123.         0x0000,
  124.         0xFFFF,
  125.         0x0000,
  126.         0xFFFF,
  127.         0x0000,
  128.         0xFFFF,
  129.         0x0000,
  130.         0xFFFF
  131.     };
  132.  
  133. unsigned short tempPattern[16];
  134.  
  135. Matrix cardBasis=
  136.     {
  137.         {-0.5,  1.5, -1.5,  0.5},
  138.         { 1.0, -2.5,  2.0, -0.5},
  139.         {-0.5,  0.0,  0.5,  0.0},
  140.         { 0.0,  1.0,  0.0,  0.0}
  141.     };
  142. #endif
  143.  
  144. typedef struct
  145.     {
  146.     Bool rWrite;
  147.     Bool gWrite;
  148.     Bool bWrite;
  149.     Bool zWrite;
  150.     } WriteMask;
  151.  
  152. #define NWRITEMASKS    10
  153. static int curWriteMask = 0;
  154.  
  155. static WriteMask writeMasks[NWRITEMASKS];
  156.  
  157. #ifdef PROTO
  158. static void SetCurMask(void)
  159. #else
  160. static void SetCurMask()
  161. #endif
  162. /*Sets the mask according to the current mask*/
  163. {
  164.     if (rgbp)
  165.     {
  166.     RGBwritemask(writeMasks[curWriteMask] . rWrite ? 0xff : 0,
  167.              writeMasks[curWriteMask] . gWrite ? 0xff : 0,
  168.              writeMasks[curWriteMask] . bWrite ? 0xff : 0);
  169.     }
  170.     zwritemask(writeMasks[curWriteMask] . zWrite ? 0xffffffff : 0);
  171. }
  172.  
  173. #ifdef PROTO
  174. void BeginMask(Bool rWrite, Bool gWrite, Bool bWrite, Bool zWrite)
  175. #else
  176. void BeginMask(rWrite, gWrite, bWrite, zWrite)
  177. #endif
  178. /*Sets up write masks to r, g, b, and z buffer.  Bracket with EndMask*/
  179. {
  180.     ++curWriteMask;
  181.  
  182.     writeMasks[curWriteMask] . rWrite = rWrite ? writeMasks[curWriteMask - 1] . rWrite : false;
  183.     writeMasks[curWriteMask] . gWrite = gWrite ? writeMasks[curWriteMask - 1] . gWrite : false;
  184.     writeMasks[curWriteMask] . bWrite = bWrite ? writeMasks[curWriteMask - 1] . bWrite : false;
  185.     writeMasks[curWriteMask] . zWrite = zWrite ? writeMasks[curWriteMask - 1] . zWrite : false;
  186.  
  187.     SetCurMask();
  188. }
  189.  
  190. #ifdef PROTO
  191. void EndMask(void)
  192. #else
  193. void EndMask()
  194. #endif
  195. /*End of a BeginMask block*/
  196. {
  197.     --curWriteMask;
  198.  
  199.     SetCurMask();
  200. }
  201.  
  202. #ifdef PROTO
  203. void OverrideColor(Bool whether)
  204. #else
  205. void OverrideColor(whether)
  206. Bool whether;
  207. #endif
  208. /*Overrides the colors in a picture*/
  209. {
  210.     overrideColor = whether;
  211. }
  212.  
  213. static ObjPtr MakePictureDeformed(picture)
  214. ObjPtr picture;
  215. /*Makes a picture's PICDEFORMED variable.  Really doesn't have to do anything*/
  216. {
  217.     SetVar(picture, PICDEFORMED, ObjTrue);
  218. }
  219.  
  220. #ifdef PROTO
  221. VertexPtr NewVertex(ObjPtr picture, int flags)
  222. #else
  223. VertexPtr NewVertex(picture, flags)
  224. ObjPtr picture;
  225. int flags;
  226. #endif
  227. /*Returns a new vertex, stuck on picture*/
  228. {
  229.     VertexPtr retVal;
  230.  
  231.     if (freedVertices)
  232.     {
  233.     retVal = freedVertices;
  234.     freedVertices = freedVertices -> next;
  235.     }
  236.     else
  237.     {
  238.     retVal = newp(Vertex);
  239.     }
  240.  
  241.     if (retVal)
  242.     {
  243.     retVal -> normal[0] = retVal -> normal[1] = 0.0;
  244.     retVal -> normal[2] = 1.0;
  245.     retVal -> position[0] = retVal -> position[1] = retVal -> position[2] = 0.0;
  246.     retVal -> colorIndex = 0;
  247.  
  248.     retVal -> next = 0;
  249.     retVal -> flags = flags;
  250.     if (((PicPtr) picture) -> lastVertex)
  251.     {
  252.         (((PicPtr) picture) -> lastVertex) -> next = retVal;
  253.         ((PicPtr) picture) -> lastVertex = retVal;
  254.     }
  255.     else
  256.     {
  257.         ((PicPtr) picture) -> lastVertex = retVal;
  258.         ((PicPtr) picture) -> vertices = retVal;
  259.     }
  260.     }
  261.     return retVal;
  262. }
  263.  
  264. #ifdef PROTO
  265. VertexPtr InsertVertex(ObjPtr picture, VertexPtr after)
  266. #else
  267. VertexPtr InsertVertex(picture, after)
  268. ObjPtr picture;
  269. VertexPtr after;
  270. #endif
  271. /*Returns a new vertex, stuck on picture after after, with VF_SAMEPLACE*/
  272. {
  273.     VertexPtr retVal;
  274.  
  275.     if (freedVertices)
  276.     {
  277.     retVal = freedVertices;
  278.     freedVertices = freedVertices -> next;
  279.     }
  280.     else
  281.     {
  282.     retVal = newp(Vertex);
  283.     }
  284.  
  285.     if (retVal)
  286.     {
  287.     retVal -> normal[0] = retVal -> normal[1] = 0.0;
  288.     retVal -> normal[2] = 1.0;
  289.     retVal -> position[0] = retVal -> position[1] = retVal -> position[2] = 0.0;
  290.     retVal -> colorIndex = 0;
  291.  
  292.     retVal -> next = after -> next;
  293.     retVal -> flags = VF_SAMEPLACE;
  294.  
  295.     after -> next = retVal;
  296.  
  297.     if (((PicPtr) picture) -> lastVertex == after)
  298.     {
  299.         ((PicPtr) picture) -> lastVertex = retVal;
  300.     }
  301.     }
  302.     return retVal;
  303. }
  304.  
  305. #ifdef PROTO
  306. void FreeVertex(VertexPtr vertex)
  307. #else
  308. void FreeVertex(vertex)
  309. VertexPtr vertex;
  310. #endif
  311. /*Frees a vertex*/
  312. {
  313.     vertex -> next = freedVertices;
  314.     freedVertices = vertex;
  315. }
  316.  
  317. static ObjPtr RegisterPicField(pic, whichField)
  318. ObjPtr pic;
  319. int whichField;
  320. /*Registers pic in a field*/
  321. {
  322.     curFields[whichField] . objectInfo = pic;
  323.     return ObjTrue;
  324. }
  325.  
  326. void InitPictures()
  327. /*Initializes the pictures system*/
  328. {
  329.     int k;
  330.     double theta;
  331.  
  332.     writeMasks[curWriteMask] . rWrite = true;
  333.     writeMasks[curWriteMask] . gWrite = true;
  334.     writeMasks[curWriteMask] . bWrite = true;
  335.     writeMasks[curWriteMask] . zWrite = true;
  336.  
  337. #ifdef GRAPHICS
  338.     deflinestyle(DASHEDLINE, dashedLine);
  339.     deflinestyle(DOTTEDLINE, dottedLine);
  340.  
  341.     /*Define the patterns*/
  342.     defpattern(GREYPAT, 16, greyPattern);
  343.     defpattern(EVENPAT, 16, evenPattern);
  344.     defpattern(ODDPAT, 16, oddPattern);
  345.  
  346.     for (k = 0; k < 16; ++k) tempPattern[k] = funkyGreyPattern[k] & evenPattern[k];
  347.     defpattern(EVENGREYPAT, 16, tempPattern);
  348.  
  349.     for (k = 0; k < 16; ++k) tempPattern[k] = funkyGreyPattern[k] & oddPattern[k];
  350.     defpattern(ODDGREYPAT, 16, tempPattern);
  351.  
  352.     /*Define the cardinal spline basis*/
  353.     defbasis(CARDBASIS, cardBasis);
  354. #endif
  355.  
  356.     picClass = NewObject(NULLOBJ, 0);
  357.     AddToReferenceList(picClass);
  358.     SetMethod(picClass, REGISTERFIELD, RegisterPicField);
  359.  
  360.     DeclareIndirectDependency(picClass, PICDEFORMED, REPOBJ, PICDEFORMED);
  361.     SetMethod(picClass, PICDEFORMED, MakePictureDeformed);
  362.  
  363.     /*Initialize cef*/
  364.     theta = M_PI_4;
  365.     for (k = 0; k < MAXSUB; ++k)
  366.     {
  367.     cefs[k] = 1.0 / rcos(theta);
  368.     cefs_2[k] = cefs[k] * 0.5;
  369.     theta *= 0.5;
  370.     }
  371. }
  372.  
  373. void KillPictures()
  374. /*Kills the pictures system*/
  375. {
  376.     DeleteThing(picClass);
  377. }
  378.  
  379. static ObjPtr CleanupPicture(pic)
  380. PicPtr pic;
  381. /*Cleans up pic*/
  382. {
  383.     while (pic -> vertices)
  384.     {
  385.     VertexPtr next;
  386.     next = pic -> vertices -> next;
  387.     Free(pic -> vertices);
  388.     pic -> vertices = next;
  389.     }
  390.     pic -> lastVertex = 0;
  391.  
  392.     while (pic -> items)
  393.     {
  394.     PicItemPtr next;
  395.     if (pic -> items -> type == POLYGONS)
  396.     {
  397.         PolyPtr runner, nr;
  398.         runner = ((PolysPtr) pic -> items) -> polygons;
  399.         while (runner)
  400.         {
  401.         nr = (PolyPtr) runner -> item . next;
  402.         Free(runner);
  403.         runner = nr;
  404.         }
  405.     }
  406.     next = pic -> items -> next;
  407.     Free(pic -> items);
  408.     pic -> items = next;
  409.     }
  410.     pic -> lastItem = 0;
  411.     return ObjTrue;
  412. }
  413.  
  414. ObjPtr NewPicture()
  415. /*Returns a new empty picture or 0 if it could not make one.*/
  416. {
  417.     PicPtr retVal;
  418.     retVal = (PicPtr) NewObject(picClass, sizeof(Picture) - sizeof(Thing));
  419.     if (retVal)
  420.     {
  421.         SETOBJTYPE(retVal -> thing . flags, PICTURE);
  422.     SetMethod((ObjPtr) retVal, CLEANUP, CleanupPicture);
  423.     retVal -> vertices = 0;
  424.     retVal -> lastVertex = 0;
  425.  
  426.     retVal -> items = 0;
  427.     retVal -> lastItem = 0;
  428.     return (ObjPtr) retVal;
  429.     }
  430.     else
  431.     {
  432.     return 0;
  433.     }
  434. }
  435.  
  436. #ifdef PROTO
  437. PolysPtr AppendPolysToPicture(ObjPtr picture)
  438. #else
  439. PolysPtr AppendPolysToPicture(picture)
  440. ObjPtr picture;
  441. #endif
  442. /*Returns a new empty set of polygons 0 if it could not make one.*/
  443. {
  444.     PolysPtr item;
  445.     item = (PolysPtr) Alloc(sizeof(Polygons));
  446.     if (item)
  447.     {
  448.     item -> item . type = POLYGONS;
  449.     item -> item . proximity = 0;
  450.     item -> item . flags = 0;
  451.  
  452.     item -> picture = (PicPtr) picture;
  453.     item -> polygons = 0;
  454.     item -> lastItem = 0;
  455.     item -> enclosed = false;
  456.  
  457.     AppendItemToPicture((PicPtr) picture, (PicItemPtr) item);
  458.     return item;
  459.     }
  460.     else
  461.     {
  462.     return 0;
  463.     }
  464. }
  465.  
  466. #ifdef PROTO
  467. PolyPtr AppendPolyToPolys(PolysPtr polys, long nVertices, Vertex vertices[])
  468. #else
  469. PolyPtr AppendPolyToPolys(polys, nVertices, vertices)
  470. PolysPtr polys;
  471. long nVertices;
  472. Vertex vertices[];
  473. #endif
  474. /*Append a polygon with nVertices where vertices is an array of Vertex
  475.   to polygons polys.  Returns true iff successful.*/
  476. {
  477.     PolyPtr item;
  478.     int k, d;
  479.  
  480.     item = (PolyPtr)
  481.        Alloc(sizeof(Polygon) + (nVertices - 1) * sizeof(VertexPtr));
  482.     if (item)
  483.     {
  484.     item -> item . type = POLYGON;
  485.     item -> item . proximity = 0;
  486.     item -> item . flags = 0;
  487.  
  488.     item -> nVertices = nVertices;
  489.     for (k = 0; k < nVertices; ++k)
  490.     {
  491.         item -> vertices[k] = NewVertex((ObjPtr) polys -> picture, 0);
  492.         for (d = 0; d < 3; ++d)
  493.         {
  494.         item -> vertices[k] -> position[d] = vertices[k] . position[d];
  495.         item -> vertices[k] -> normal[d] = vertices[k] . normal[d];
  496.         }
  497.         item -> vertices[k] -> colorIndex = vertices[k] . colorIndex;
  498.     }
  499.     if (polys -> polygons)
  500.     {
  501.         /*It's not the first*/
  502.         polys -> lastItem -> item . next = (PicItemPtr) item;
  503.     }
  504.     else
  505.     {
  506.         /*It is the first*/
  507.         polys -> polygons = item;
  508.     }
  509.     item -> item . next = 0;
  510.     polys -> lastItem = item;
  511.     return item;
  512.     }
  513.     else
  514.     {
  515.     OMErr();
  516.     return 0;
  517.     }
  518. }
  519.  
  520. #ifdef PROTO
  521. PolyPtr AppendSPolyToPolys(PolysPtr polys, long nVertices, VertexPtr vertices[])
  522. #else
  523. PolyPtr AppendSPolyToPolys(polys, nVertices, vertices)
  524. PolysPtr polys;
  525. long nVertices;
  526. VertexPtr vertices[];
  527. #endif
  528. /*Append a polygon with nVertices where vertices is an array of VertexPtr
  529.   to polygons polys.  Returns true iff successful.  The vertices are 
  530.   presumed to be shared.*/
  531. {
  532.     PolyPtr item;
  533.     int k, d;
  534.  
  535.     item = (PolyPtr)
  536.        Alloc(sizeof(Polygon) + (nVertices - 1) * sizeof(VertexPtr));
  537.     if (item)
  538.     {
  539.     item -> item . type = POLYGON;
  540.     item -> item . proximity = 0;
  541.     item -> item . flags = 0;
  542.  
  543.     item -> nVertices = nVertices;
  544.     for (k = 0; k < nVertices; ++k)
  545.     {
  546.         item -> vertices[k] = vertices[k];
  547.         for (d = 0; d < 3; ++d)
  548.         {
  549.         item -> vertices[k] -> position[d] = vertices[k] -> position[d];
  550.         item -> vertices[k] -> normal[d] = vertices[k] -> normal[d];
  551.         }
  552.         item -> vertices[k] -> colorIndex = vertices[k] -> colorIndex;
  553.     }
  554.     if (polys -> polygons)
  555.     {
  556.         /*It's not the first*/
  557.         polys -> lastItem -> item . next = (PicItemPtr) item;
  558.     }
  559.     else
  560.     {
  561.         /*It is the first*/
  562.         polys -> polygons = item;
  563.     }
  564.     item -> item . next = 0;
  565.     polys -> lastItem = item;
  566.     return item;
  567.     }
  568.     else
  569.     {
  570.     OMErr();
  571.     return 0;
  572.     }
  573. }
  574.  
  575. #ifdef PROTO
  576. PolyPtr TesselateSPolyToPicture(ObjPtr pic, long nVertices, VertexPtr vertices[])
  577. #else
  578. PolyPtr TesselateSPolyToPicture(pic, nVertices, vertices)
  579. ObjPtr pic;
  580. long nVertices;
  581. VertexPtr vertices[];
  582. #endif
  583. /*Tesselates a polygon with nVertices where vertices is an array of VertexPtr
  584.   to picture pic.  Returns the resulting item iff successful.  The vertices are 
  585.   presumed to be shared.  It's a very simple-minded tesselation, not guaranteed
  586.   to work for non convex polygons*/
  587. {
  588.     PolyPtr item;
  589.     int k, d;
  590.     register VertexPtr *v1, *v2;
  591.  
  592.     v1 = vertices;
  593.     v2 = vertices + nVertices - 1;
  594.  
  595.  
  596.     item = (PolyPtr)
  597.        Alloc(sizeof(Polygon) + (nVertices - 1) * sizeof(VertexPtr));
  598.     if (item)
  599.     {
  600.     item -> item . type = POLYTRI;
  601.     item -> item . proximity = 0;
  602.     item -> item . flags = 0;
  603.  
  604.     item -> nVertices = nVertices;
  605.  
  606.     /*Fill the vertices*/
  607.     k = 0;
  608.  
  609.     item -> vertices[k++] = *(v1++);
  610.     while (v2 >= v1)
  611.     {
  612.         item -> vertices[k++] = *(v1++);
  613.         if (v2 >= v1)
  614.         {
  615.         item -> vertices[k++] = *(v2--);
  616.         }
  617.     }
  618.     AppendItemToPicture((PicPtr) pic, (PicItemPtr) item);
  619.     return item;
  620.     }
  621.     else
  622.     {
  623.     OMErr();
  624.     return 0;
  625.     }
  626. }
  627.  
  628. #ifdef PROTO
  629. static PolyPtr ConvertPolyOntoPolys(PolysPtr polys, PolyPtr poly)
  630. #else
  631. static PolyPtr ConvertPolyOntoPolys(polys, poly)
  632. PolysPtr polys;
  633. PolyPtr poly;
  634. #endif
  635. /*Append a polygon with nVertices where vertices is an array of Vertex
  636.   to polygons polys.  Returns true iff successful.*/
  637. {
  638.     PolyPtr item;
  639.     int k, d;
  640.  
  641.     item = (PolyPtr)
  642.        Alloc(sizeof(Polygon) + (poly -> nVertices - 1) * sizeof(VertexPtr));
  643.     if (item)
  644.     {
  645.     item -> item . type = POLYGON;
  646.     item -> item . proximity = poly -> item . proximity;
  647.     item -> item . flags = 0;
  648.  
  649.     item -> nVertices = poly -> nVertices;
  650.     for (k = 0; k < poly -> nVertices; ++k)
  651.     {
  652.         item -> vertices[k] = NewVertex((ObjPtr) polys -> picture, 0);
  653.         for (d = 0; d < 3; ++d)
  654.         {
  655.         item -> vertices[k] -> position[d] =
  656.             poly -> vertices[k] -> position[d];
  657.         item -> vertices[k] -> normal[d] =
  658.             poly -> vertices[k] -> normal[d];
  659.         }
  660.         item -> vertices[k] -> colorIndex =
  661.         poly -> vertices[k] -> colorIndex;
  662.     }
  663.     if (polys -> polygons)
  664.     {
  665.         /*It's not the first*/
  666.         polys -> lastItem -> item . next = (PicItemPtr) item;
  667.     }
  668.     else
  669.     {
  670.         /*It is the first*/
  671.         polys -> polygons = item;
  672.     }
  673.     item -> item . next = 0;
  674.     polys -> lastItem = item;
  675.     return item;
  676.     }
  677.     else
  678.     {
  679.     OMErr();
  680.     return 0;
  681.     }
  682. }
  683.  
  684. static void AppendItemToPicture(pic, item)
  685. PicPtr pic;
  686. PicItemPtr item;
  687. /*Appends item to the end of pic*/
  688. {
  689.     if (pic -> items)
  690.     {
  691.     /*It's not the first*/
  692.     pic -> lastItem -> next = item;
  693.     }
  694.     else
  695.     {
  696.     /*It is the first*/
  697.     pic -> items = item;
  698.     }
  699.     item -> next = 0;
  700.     pic -> lastItem = item;
  701. }
  702.  
  703. #ifdef PROTO
  704. RectMeshPtr AppendRectMeshToPicture(ObjPtr picture, long xDim, long yDim, Bool inCenter)
  705. #else
  706. RectMeshPtr AppendRectMeshToPicture(picture, xDim, yDim, inCenter)
  707. ObjPtr picture;
  708. long yDim, xDim;
  709. Bool inCenter;
  710. #endif
  711. /*Appends a new rectangular mesh.  inCenter if nodes in center*/
  712. {
  713.     RectMeshPtr item;
  714.     long nVertices;
  715.     long k;
  716.  
  717.     nVertices = (xDim * (2 * yDim - 1));
  718.     item = (RectMeshPtr)
  719.        Alloc(sizeof(RectMesh) + (nVertices - 1) *
  720.             sizeof(VertexPtr));
  721.     for (k = 0; k < nVertices; ++k)
  722.     {
  723.     item -> vertices[k] = NewVertex(picture, 0);
  724.     }
  725.     item -> item . type = RECTMESH;
  726.     item -> item . proximity = 0;
  727.     item -> item . flags = 0;
  728.  
  729.     item -> inCenter = inCenter;
  730.     item -> xDim = xDim;
  731.     item -> yDim = yDim;
  732.  
  733.     AppendItemToPicture((PicPtr) picture, (PicItemPtr) item);
  734.     return item;
  735. }
  736.  
  737. #ifdef PROTO
  738. VertexPtr RectMeshVertex(RectMeshPtr rectMesh, long i, long j)
  739. #else
  740. VertexPtr RectMeshVertex(rectMesh, i, j)
  741. RectMeshPtr rectMesh;
  742. long i, j;
  743. #endif
  744. /*Returns vertex i, j of a rect mesh*/
  745. {
  746.     long offset;
  747.     offset = RECTMESHVERTEX(rectMesh, i, j);
  748.     return rectMesh -> vertices[offset]; 
  749. }
  750.  
  751. #ifdef PROTO
  752. VertexPtr RectMeshCenter(RectMeshPtr rectMesh, long i, long j)
  753. #else
  754. VertexPtr RectMeshCenter(rectMesh, i, j)
  755. RectMeshPtr rectMesh;
  756. long i, j;
  757. #endif
  758. /*Returns center i, j of a rect mesh*/
  759. {
  760.     long offset;
  761.     offset = RECTMESHCENTER(rectMesh, i, j);
  762.     return rectMesh -> vertices[offset]; 
  763. }
  764.  
  765.  
  766. #ifdef PROTO
  767. void CalcRectNormals(RectMeshPtr rectMesh)
  768. #else
  769. void CalcRectNormals(rectMesh)
  770. RectMeshPtr rectMesh;
  771. #endif
  772. /*Calculates the normals in rectMesh and copies them to the vertices.
  773.   Obviously, do this after the positions have been set.*/
  774. {
  775.     register long i, j, k, offset, offset2, offset3, iDim, jDim, nX, nY;
  776.     register VertexPtr *vertices;
  777.     float normal[3];        /*Normal at center vertex*/
  778.     float position1[3];        /*Position of base vertex*/
  779.     float vI[3], vJ[3];        /*Vectors for cross product*/
  780.     float vt[3];        /*Test vertex*/
  781.  
  782.     iDim = rectMesh -> xDim;
  783.     jDim = rectMesh -> yDim;
  784.     vertices = rectMesh -> vertices;
  785.     nX = jDim * 2 - 1;
  786. #define nY 2
  787.  
  788.     /*Make all the _vertex_ normals*/
  789.     for (j = 0; j < jDim; ++j)
  790.     {
  791.     for (i = 0; i < iDim; ++i)
  792.     {
  793.         vI[0] = vI[1] = vI[2] = 0.0;
  794.         vJ[0] = vJ[1] = vJ[2] = 0.0;
  795.  
  796.         offset = RECTMESHVERTEX(rectMesh, i, j);
  797.  
  798.         /*Get position here at vertex*/
  799.         position1[0] = vertices[offset] -> position[0];
  800.         position1[1] = vertices[offset] -> position[1];
  801.         position1[2] = vertices[offset] -> position[2];
  802.  
  803.         /*Make i component*/
  804.         if (i >= iDim - 1)
  805.         {
  806.         /*Get from i - 1*/
  807.         offset2 = offset - nX;
  808.         vI[0] += position1[0] - vertices[offset2] -> position[0];
  809.         vI[1] += position1[1] - vertices[offset2] -> position[1];
  810.         vI[2] += position1[2] - vertices[offset2] -> position[2];
  811.         }
  812.         else if (i <= 0)
  813.         {
  814.         /*Get from i + 1*/
  815.         offset2 = offset + nX;
  816.         vI[0] += vertices[offset2] -> position[0] - position1[0];
  817.         vI[1] += vertices[offset2] -> position[1] - position1[1];
  818.         vI[2] += vertices[offset2] -> position[2] - position1[2];
  819.         }
  820.         else
  821.         {
  822.         /*Get from i + 1 and i - 1*/
  823.         offset2 = offset - nX;
  824.         offset3 = offset + nX;
  825.         vI[0] += vertices[offset3] -> position[0] - vertices[offset2] -> position[0];
  826.         vI[1] += vertices[offset3] -> position[1] - vertices[offset2] -> position[1];
  827.         vI[2] += vertices[offset3] -> position[2] - vertices[offset2] -> position[2];
  828.         }
  829.  
  830.         /*Make j component*/
  831.         if (j >= jDim - 1)
  832.         {
  833.         /*Get from j - 1*/
  834.         offset2 = offset - nY;
  835.         vJ[0] += position1[0] - vertices[offset2] -> position[0];
  836.         vJ[1] += position1[1] - vertices[offset2] -> position[1];
  837.         vJ[2] += position1[2] - vertices[offset2] -> position[2];
  838.         }
  839.         else if (j <= 0)
  840.         {
  841.         /*Get from j + 1*/
  842.         offset2 = offset + nY;
  843.         vJ[0] += vertices[offset2] -> position[0] - position1[0];
  844.         vJ[1] += vertices[offset2] -> position[1] - position1[1];
  845.         vJ[2] += vertices[offset2] -> position[2] - position1[2];
  846.         }
  847.         else
  848.         {
  849.         /*Get from j + 1 and j - 1*/
  850.         offset2 = offset - nY;
  851.         offset3 = offset + nY;
  852.         vJ[0] += vertices[offset3] -> position[0] - vertices[offset2] -> position[0];
  853.         vJ[1] += vertices[offset3] -> position[1] - vertices[offset2] -> position[1];
  854.         vJ[2] += vertices[offset3] -> position[2] - vertices[offset2] -> position[2];
  855.         }
  856.  
  857.         /*Cross i by j to get normal*/
  858.         CROSS(vI, vJ, normal);
  859.  
  860.         if (normal[0] == 0.0 && normal[1] == 0.0 && normal[2] == 0.0)
  861.         {
  862.         normal[2] = 1.0;
  863.         }
  864.  
  865.         /*Normalize it*/
  866.         NORMALIZE(normal);
  867.  
  868.         vertices[offset] -> normal[0] += normal[0];
  869.         vertices[offset] -> normal[1] += normal[1];
  870.         vertices[offset] -> normal[2] += normal[2];
  871.     }
  872.     }
  873.  
  874. #undef nY
  875.  
  876.     /*Interpolate the centers with four corners*/
  877.     for (i = 1; i < iDim - 1; ++i)
  878.     {
  879.     for (j = 1; j < jDim - 1; ++j)
  880.     {
  881.         /*Lower left corner*/
  882.         offset = RECTMESHVERTEX(rectMesh, i - 1, j - 1);
  883.         normal[0] = vertices[offset] -> normal[0];
  884.         normal[1] = vertices[offset] -> normal[1];
  885.         normal[2] = vertices[offset] -> normal[2];
  886.  
  887.         /*Upper left corner*/
  888.         offset = RECTMESHVERTEX(rectMesh, i - 1, j);
  889.         normal[0] += vertices[offset] -> normal[0];
  890.         normal[1] += vertices[offset] -> normal[1];
  891.         normal[2] += vertices[offset] -> normal[2];
  892.  
  893.         /*Lower right corner*/
  894.         offset = RECTMESHVERTEX(rectMesh, i, j - 1);
  895.         normal[0] += vertices[offset] -> normal[0];
  896.         normal[1] += vertices[offset] -> normal[1];
  897.         normal[2] += vertices[offset] -> normal[2];
  898.  
  899.         /*Upper right corner*/
  900.         offset = RECTMESHVERTEX(rectMesh, i, j);
  901.         normal[0] += vertices[offset] -> normal[0];
  902.         normal[1] += vertices[offset] -> normal[1];
  903.         normal[2] += vertices[offset] -> normal[2];
  904.  
  905.         if (normal[0] == 0.0 && normal[1] == 0.0 && normal[2] == 0.0)
  906.         {
  907.         normal[2] = 1.0;
  908.         }
  909.  
  910.         /*Normalize it*/
  911.         NORMALIZE(normal);
  912.  
  913.         /*Stuff them*/
  914.         offset = RECTMESHCENTER(rectMesh, i, j);
  915.         vertices[offset] -> normal[0] += normal[0];
  916.         vertices[offset] -> normal[1] += normal[1];
  917.         vertices[offset] -> normal[2] += normal[2];
  918.     }
  919.     }
  920. }
  921.  
  922. #ifdef PROTO
  923. void InterpRectCenters(RectMeshPtr rectMesh)
  924. #else
  925. void InterpRectCenters(rectMesh)
  926. RectMeshPtr rectMesh;
  927. #endif
  928. /*Interpolates rect centers from vertices*/
  929. {
  930.     register long i, j, offset, iDim, jDim, nX;
  931.     register VertexPtr *vertices;
  932.     float position[3];        /*Position of center vertex*/
  933.     int colorIndex;        /*Color within color table*/
  934.  
  935.     iDim = rectMesh -> xDim;
  936.     jDim = rectMesh -> yDim;
  937.     vertices = rectMesh -> vertices;
  938.     nX = jDim * 2 - 1;
  939.  
  940.     for (i = 0; i < iDim - 1; ++i)
  941.     {
  942.     for (j = 0; j < jDim - 1; ++j)
  943.     {
  944.         /*Lower left corner*/
  945.         offset = RECTMESHVERTEX(rectMesh, i, j);
  946.         position[0] = vertices[offset] -> position[0];
  947.         position[1] = vertices[offset] -> position[1];
  948.         position[2] = vertices[offset] -> position[2];
  949.         colorIndex = vertices[offset] -> colorIndex;
  950.  
  951.         /*Upper left corner*/
  952.         offset = RECTMESHVERTEX(rectMesh, i, j + 1);
  953.         position[0] += vertices[offset] -> position[0];
  954.         position[1] += vertices[offset] -> position[1];
  955.         position[2] += vertices[offset] -> position[2];
  956.         colorIndex += vertices[offset] -> colorIndex;
  957.  
  958.         /*Lower right corner*/
  959.         offset = RECTMESHVERTEX(rectMesh, i + 1, j);
  960.         position[0] += vertices[offset] -> position[0];
  961.         position[1] += vertices[offset] -> position[1];
  962.         position[2] += vertices[offset] -> position[2];
  963.         colorIndex += vertices[offset] -> colorIndex;
  964.  
  965.         /*Upper right corner*/
  966.         offset = RECTMESHVERTEX(rectMesh, i + 1, j + 1);
  967.         position[0] += vertices[offset] -> position[0];
  968.         position[1] += vertices[offset] -> position[1];
  969.         position[2] += vertices[offset] -> position[2];
  970.         colorIndex += vertices[offset] -> colorIndex;
  971.  
  972.         /*Normalize results*/
  973.         position[0] *= 0.25;
  974.         position[1] *= 0.25;
  975.         position[2] *= 0.25;
  976.         colorIndex /= 4;
  977.  
  978.         /*Stuff them*/
  979.         offset = RECTMESHCENTER(rectMesh, i, j);
  980.         vertices[offset] -> position[0] = position[0];
  981.         vertices[offset] -> position[1] = position[1];
  982.         vertices[offset] -> position[2] = position[2];
  983.         vertices[offset] -> colorIndex = colorIndex;
  984.     }
  985.     }
  986. }
  987.  
  988. #ifdef PROTO
  989. void InterpRectVertices(RectMeshPtr rectMesh)
  990. #else
  991. void InterpRectVertices(rectMesh)
  992. RectMeshPtr rectMesh;
  993. #endif
  994. /*Interpolates and extrapolates rect vertices from centers*/
  995. {
  996.     register long i, j, k, offset, iDim, jDim, nX;
  997.     register VertexPtr *vertices;
  998.     float position[3];        /*Position of center vertex*/
  999.     int colorIndex;        /*Color within color table*/
  1000.  
  1001.     iDim = rectMesh -> xDim;
  1002.     jDim = rectMesh -> yDim;
  1003.  
  1004.     vertices = rectMesh -> vertices;
  1005.     nX = jDim * 2 - 1;
  1006.  
  1007.     /*Interpolate the centers with four corners*/
  1008.     for (i = 1; i < iDim - 1; ++i)
  1009.     {
  1010.     for (j = 1; j < jDim - 1; ++j)
  1011.     {
  1012.         /*Lower left corner*/
  1013.         offset = RECTMESHCENTER(rectMesh, i - 1, j - 1);
  1014.         position[0] = vertices[offset] -> position[0];
  1015.         position[1] = vertices[offset] -> position[1];
  1016.         position[2] = vertices[offset] -> position[2];
  1017.         colorIndex = vertices[offset] -> colorIndex;
  1018.  
  1019.         /*Upper left corner*/
  1020.         offset = RECTMESHCENTER(rectMesh, i - 1, j);
  1021.         position[0] += vertices[offset] -> position[0];
  1022.         position[1] += vertices[offset] -> position[1];
  1023.         position[2] += vertices[offset] -> position[2];
  1024.         colorIndex += vertices[offset] -> colorIndex;
  1025.  
  1026.         /*Lower right corner*/
  1027.         offset = RECTMESHCENTER(rectMesh, i, j - 1);
  1028.         position[0] += vertices[offset] -> position[0];
  1029.         position[1] += vertices[offset] -> position[1];
  1030.         position[2] += vertices[offset] -> position[2];
  1031.         colorIndex += vertices[offset] -> colorIndex;
  1032.  
  1033.         /*Upper right corner*/
  1034.         offset = RECTMESHCENTER(rectMesh, i, j);
  1035.         position[0] += vertices[offset] -> position[0];
  1036.         position[1] += vertices[offset] -> position[1];
  1037.         position[2] += vertices[offset] -> position[2];
  1038.         colorIndex += vertices[offset] -> colorIndex;
  1039.  
  1040.         /*Normalize results*/
  1041.         position[0] *= 0.25;
  1042.         position[1] *= 0.25;
  1043.         position[2] *= 0.25;
  1044.         colorIndex /= 4;
  1045.  
  1046.         /*Stuff them*/
  1047.         offset = RECTMESHVERTEX(rectMesh, i, j);
  1048.         vertices[offset] -> position[0] = position[0];
  1049.         vertices[offset] -> position[1] = position[1];
  1050.         vertices[offset] -> position[2] = position[2];
  1051.         vertices[offset] -> colorIndex = colorIndex;
  1052.     }
  1053.     }
  1054.  
  1055.     /*Extrapolate left and right sides*/
  1056.     for (j = 1; j < jDim - 1; ++j)
  1057.     {
  1058.     /*Left side*/
  1059.     offset = RECTMESHVERTEX(rectMesh, 1, j);
  1060.     for (k = 0; k < 3; ++k)
  1061.     {
  1062.         position[k] = vertices[offset] -> position[k];
  1063.     }
  1064.     colorIndex = vertices[offset] -> colorIndex;
  1065.     if (iDim >= 3)
  1066.     {
  1067.         /*Extend position only*/
  1068.         offset = RECTMESHVERTEX(rectMesh, 2, j);
  1069.         for (k = 0; k < 3; ++k)
  1070.         {
  1071.         position[k] += position[k] - vertices[offset] -> position[k];
  1072.         }
  1073.     }
  1074.     /*Stuff them back*/
  1075.     offset = RECTMESHVERTEX(rectMesh, 0, j);
  1076.     for (k = 0; k < 3; ++k)
  1077.     {
  1078.         vertices[offset] -> position[k] = position[k];
  1079.     }
  1080.     vertices[offset] -> colorIndex = colorIndex;
  1081.  
  1082.     /*Right side*/
  1083.     offset = RECTMESHVERTEX(rectMesh, iDim - 2, j);
  1084.     for (k = 0; k < 3; ++k)
  1085.     {
  1086.         position[k] = vertices[offset] -> position[k];
  1087.     }
  1088.     colorIndex = vertices[offset] -> colorIndex;
  1089.     if (iDim >= 3)
  1090.     {
  1091.         /*Extend position only*/
  1092.         offset = RECTMESHVERTEX(rectMesh, iDim - 3, j);
  1093.         for (k = 0; k < 3; ++k)
  1094.         {
  1095.         position[k] += position[k] - vertices[offset] -> position[k];
  1096.         }
  1097.     }
  1098.     /*Stuff them back*/
  1099.     offset = RECTMESHVERTEX(rectMesh, iDim - 1, j);
  1100.     for (k = 0; k < 3; ++k)
  1101.     {
  1102.         vertices[offset] -> position[k] = position[k];
  1103.     }
  1104.     vertices[offset] -> colorIndex = colorIndex;
  1105.     }    
  1106.  
  1107.     /*Extrapolate bottom and top sides*/
  1108.     for (i = 1; i < iDim - 1; ++i)
  1109.     {
  1110.     /*Left side*/
  1111.     offset = RECTMESHVERTEX(rectMesh, i, 1);
  1112.     for (k = 0; k < 3; ++k)
  1113.     {
  1114.         position[k] = vertices[offset] -> position[k];
  1115.     }
  1116.     colorIndex = vertices[offset] -> colorIndex;
  1117.     if (jDim >= 3)
  1118.     {
  1119.         /*Extend position only*/
  1120.         offset = RECTMESHVERTEX(rectMesh, i, 2);
  1121.         for (k = 0; k < 3; ++k)
  1122.         {
  1123.         position[k] += position[k] - vertices[offset] -> position[k];
  1124.         }
  1125.     }
  1126.     /*Stuff them back*/
  1127.     offset = RECTMESHVERTEX(rectMesh, i, 0);
  1128.     for (k = 0; k < 3; ++k)
  1129.     {
  1130.         vertices[offset] -> position[k] = position[k];
  1131.     }
  1132.     vertices[offset] -> colorIndex = colorIndex;
  1133.  
  1134.     /*Right side*/
  1135.     offset = RECTMESHVERTEX(rectMesh, i, jDim - 2);
  1136.     for (k = 0; k < 3; ++k)
  1137.     {
  1138.         position[k] = vertices[offset] -> position[k];
  1139.     }
  1140.     colorIndex = vertices[offset] -> colorIndex;
  1141.     if (jDim >= 3)
  1142.     {
  1143.         /*Extend position only*/
  1144.         offset = RECTMESHVERTEX(rectMesh, i, jDim - 3);
  1145.         for (k = 0; k < 3; ++k)
  1146.         {
  1147.         position[k] += position[k] - vertices[offset] -> position[k];
  1148.         }
  1149.     }
  1150.     /*Stuff them back*/
  1151.     offset = RECTMESHVERTEX(rectMesh, i, jDim - 1);
  1152.     for (k = 0; k < 3; ++k)
  1153.     {
  1154.         vertices[offset] -> position[k] = position[k];
  1155.     }
  1156.     vertices[offset] -> colorIndex = colorIndex;
  1157.     }
  1158.  
  1159.     /*Do lower left corner*/
  1160.     offset = RECTMESHCENTER(rectMesh, 0, 0);
  1161.     for (k = 0; k < 3; ++k)
  1162.     {
  1163.     position[k] = vertices[offset] -> position[k];
  1164.     }
  1165.     colorIndex = vertices[offset] -> colorIndex;
  1166.  
  1167.     offset = RECTMESHVERTEX(rectMesh, 1, 1);
  1168.     for (k = 0; k < 3; ++k)
  1169.     {
  1170.     position[k] += position[k] - vertices[offset] -> position[k];
  1171.     }
  1172.     offset = RECTMESHVERTEX(rectMesh, 0, 0);
  1173.     for (k = 0; k < 3; ++k)
  1174.     {
  1175.     vertices[offset] -> position[k] = position[k];
  1176.     }
  1177.     vertices[offset] -> colorIndex = colorIndex;
  1178.  
  1179.     /*Do upper left corner*/
  1180.     offset = RECTMESHCENTER(rectMesh, 0, jDim - 2);
  1181.     for (k = 0; k < 3; ++k)
  1182.     {
  1183.     position[k] = vertices[offset] -> position[k];
  1184.     }
  1185.     colorIndex = vertices[offset] -> colorIndex;
  1186.  
  1187.     offset = RECTMESHVERTEX(rectMesh, 1, jDim - 2);
  1188.     for (k = 0; k < 3; ++k)
  1189.     {
  1190.     position[k] += position[k] - vertices[offset] -> position[k];
  1191.     }
  1192.     offset = RECTMESHVERTEX(rectMesh, 0, jDim - 1);
  1193.     for (k = 0; k < 3; ++k)
  1194.     {
  1195.     vertices[offset] -> position[k] = position[k];
  1196.     }
  1197.     vertices[offset] -> colorIndex = colorIndex;
  1198.  
  1199.     /*Do lower right corner*/
  1200.     offset = RECTMESHCENTER(rectMesh, iDim - 2, 0);
  1201.     for (k = 0; k < 3; ++k)
  1202.     {
  1203.     position[k] = vertices[offset] -> position[k];
  1204.     }
  1205.     colorIndex = vertices[offset] -> colorIndex;
  1206.  
  1207.     offset = RECTMESHVERTEX(rectMesh, iDim - 2, 1);
  1208.     for (k = 0; k < 3; ++k)
  1209.     {
  1210.     position[k] += position[k] - vertices[offset] -> position[k];
  1211.     }
  1212.     offset = RECTMESHVERTEX(rectMesh, iDim - 1, 0);
  1213.     for (k = 0; k < 3; ++k)
  1214.     {
  1215.     vertices[offset] -> position[k] = position[k];
  1216.     }
  1217.     vertices[offset] -> colorIndex = colorIndex;
  1218.  
  1219.     /*Do upper left corner*/
  1220.     offset = RECTMESHCENTER(rectMesh, iDim - 2, jDim - 2);
  1221.     for (k = 0; k < 3; ++k)
  1222.     {
  1223.     position[k] = vertices[offset] -> position[k];
  1224.     }
  1225.     colorIndex = vertices[offset] -> colorIndex;
  1226.  
  1227.     offset = RECTMESHVERTEX(rectMesh, iDim - 2, jDim - 2);
  1228.     for (k = 0; k < 3; ++k)
  1229.     {
  1230.     position[k] += position[k] - vertices[offset] -> position[k];
  1231.     }
  1232.     offset = RECTMESHVERTEX(rectMesh, iDim - 1, jDim - 1);
  1233.     for (k = 0; k < 3; ++k)
  1234.     {
  1235.     vertices[offset] -> position[k] = position[k];
  1236.     }
  1237.     vertices[offset] -> colorIndex = colorIndex;
  1238. }
  1239.  
  1240. #ifdef PROTO
  1241. PolyPtr AppendPolyToPicture(ObjPtr pic, long nVertices, Vertex vertices[])
  1242. #else
  1243. PolyPtr AppendPolyToPicture(pic, nVertices, vertices)
  1244. ObjPtr pic;
  1245. long nVertices;
  1246. Vertex vertices[];
  1247. #endif
  1248. /*Append a polygon with nVertices where vertices is an array of Vertex
  1249.   to picture pic.  Returns polygon iff successful.*/
  1250. {
  1251.     PolyPtr item;
  1252.     int k, d;
  1253.  
  1254.     item = (PolyPtr)
  1255.        Alloc(sizeof(Polygon) + (nVertices - 1) * sizeof(VertexPtr));
  1256.     if (item)
  1257.     {
  1258.     item -> item . type = POLYGON;
  1259.     item -> item . proximity = 0;
  1260.     item -> item . flags = 0;
  1261.  
  1262.     item -> nVertices = nVertices;
  1263.     for (k = 0; k < nVertices; ++k)
  1264.     {
  1265.         item -> vertices[k] = NewVertex(pic, 0);
  1266.         for (d = 0; d < 3; ++d)
  1267.         {
  1268.         item -> vertices[k] -> position[d] = vertices[k] . position[d];
  1269.         item -> vertices[k] -> normal[d] = vertices[k] . normal[d];
  1270.         }
  1271.         item -> vertices[k] -> colorIndex = vertices[k] . colorIndex;
  1272.     }
  1273.     AppendItemToPicture((PicPtr) pic, (PicItemPtr) item);
  1274.     return item;
  1275.     }
  1276.     else
  1277.     {
  1278.     return 0;
  1279.     }
  1280. }
  1281.  
  1282. #ifdef PROTO
  1283. static PolyPtr ConvertPolyOntoPicture(ObjPtr pic, PolyPtr poly)
  1284. #else
  1285. static PolyPtr ConvertPolyOntoPicture(pic, poly)
  1286. ObjPtr pic;
  1287. PolyPtr poly;
  1288. #endif
  1289. /*Converts a polygon or polyline onto picture.*/
  1290. {
  1291.     PolyPtr item;
  1292.     int k, d;
  1293.  
  1294.     item = (PolyPtr)
  1295.        Alloc(sizeof(Polygon) + (poly -> nVertices - 1) * sizeof(VertexPtr));
  1296.     if (item)
  1297.     {
  1298.     item -> item . type = poly -> item . type;
  1299.     item -> lineWidth = poly -> lineWidth;
  1300.     item -> item . proximity = poly -> item . proximity;
  1301.     item -> item . flags = 0;
  1302.  
  1303.     item -> nVertices = poly -> nVertices;
  1304.     for (k = 0; k < poly -> nVertices; ++k)
  1305.     {
  1306.         item -> vertices[k] = NewVertex(pic, 0);
  1307.         for (d = 0; d < 3; ++d)
  1308.         {
  1309.         item -> vertices[k] -> position[d] =
  1310.             poly -> vertices[k] -> position[d];
  1311.         item -> vertices[k] -> normal[d] =
  1312.             poly -> vertices[k] -> normal[d];
  1313.         }
  1314.         item -> vertices[k] -> colorIndex =
  1315.         poly -> vertices[k] -> colorIndex;
  1316.     }
  1317.     AppendItemToPicture((PicPtr) pic, (PicItemPtr) item);
  1318.     return item;
  1319.     }
  1320.     else
  1321.     {
  1322.     return 0;
  1323.     }
  1324. }
  1325.  
  1326. #ifdef PROTO
  1327. PolyPtr AppendPolylineToPicture(ObjPtr pic, int lineWidth, int proximity, long nVertices, Vertex vertices[])
  1328. #else
  1329. PolyPtr AppendPolylineToPicture(pic, lineWidth, proximity, nVertices, vertices)
  1330. ObjPtr pic;
  1331. int lineWidth;
  1332. int proximity;
  1333. long nVertices;
  1334. Vertex vertices[];
  1335. #endif
  1336. /*Append a polyline with nVertices where vertices is an array of Vertex
  1337.   to picture pic.  proximity is extra proximity for lines that are to
  1338.   go above something.  Returns true iff successful.*/
  1339. {
  1340.     PolyPtr item;
  1341.     int k, d;
  1342.  
  1343.     item = (PolyPtr)
  1344.        Alloc(sizeof(Polygon) + (nVertices - 1) * sizeof(VertexPtr));
  1345.     if (item)
  1346.     {
  1347.     item -> item . type = POLYLINE;
  1348.     item -> item . proximity = proximity;
  1349.     item -> item . flags = 0;
  1350.  
  1351.     item -> lineWidth = lineWidth;
  1352.     item -> nVertices = nVertices;
  1353.     for (k = 0; k < nVertices; ++k)
  1354.     {
  1355.         item -> vertices[k] = NewVertex(pic, 0);
  1356.         for (d = 0; d < 3; ++d)
  1357.         {
  1358.         item -> vertices[k] -> position[d] = vertices[k] . position[d];
  1359.         item -> vertices[k] -> normal[d] = vertices[k] . normal[d];
  1360.         }
  1361.         item -> vertices[k] -> colorIndex = vertices[k] . colorIndex;
  1362.     }
  1363.     AppendItemToPicture((PicPtr) pic, (PicItemPtr) item);
  1364.     return item;
  1365.     }
  1366.     else
  1367.     {
  1368.     return 0;
  1369.     }
  1370. }
  1371.  
  1372. #ifdef PROTO
  1373. PolyPtr AppendSPolylineToPicture(ObjPtr pic, int lineWidth, int proximity, long nVertices, VertexPtr vertices[])
  1374. #else
  1375. PolyPtr AppendSPolylineToPicture(pic, lineWidth, proximity, nVertices, vertices)
  1376. ObjPtr pic;
  1377. int lineWidth;
  1378. int proximity;
  1379. long nVertices;
  1380. VertexPtr vertices[];
  1381. #endif
  1382. /*Append a polyline with nVertices where vertices is an array of Vertex
  1383.   to picture pic.  proximity is extra proximity for lines that are to
  1384.   go above something.  Returns true iff successful.*/
  1385. {
  1386.     register PolyPtr item;
  1387.     register int k, d;
  1388.  
  1389.     item = (PolyPtr)
  1390.        Alloc(sizeof(Polygon) + (nVertices - 1) * sizeof(VertexPtr));
  1391.     if (item)
  1392.     {
  1393.     item -> item . type = POLYLINE;
  1394.     item -> item . proximity = proximity;
  1395.     item -> item . flags = 0;
  1396.  
  1397.     item -> lineWidth = lineWidth;
  1398.     item -> nVertices = nVertices;
  1399.     for (k = 0; k < nVertices; ++k)
  1400.     {
  1401.         item -> vertices[k] = vertices[k];
  1402.     }
  1403.     AppendItemToPicture((PicPtr) pic, (PicItemPtr) item);
  1404.     return item;
  1405.     }
  1406.     else
  1407.     {
  1408.     return 0;
  1409.     }
  1410. }
  1411.  
  1412. #ifdef PROTO
  1413. PolyPtr AppendSPolypointToPicture(ObjPtr pic, int proximity, long nVertices, VertexPtr vertices[])
  1414. #else
  1415. PolyPtr AppendSPolypointToPicture(pic, proximity, nVertices, vertices)
  1416. ObjPtr pic;
  1417. int lineWidth;
  1418. int proximity;
  1419. long nVertices;
  1420. Vertex *vertices[];
  1421. #endif
  1422. /*Append a polypoint with nVertices where vertices is an array of VertexPtr
  1423.   to picture pic.  proximity is extra proximity for points that are to
  1424.   go above something.  Returns true iff successful.*/
  1425. {
  1426.     PolyPtr item;
  1427.     int k;
  1428.  
  1429.     item = (PolyPtr)
  1430.        Alloc(sizeof(Polygon) + (nVertices - 1) * sizeof(VertexPtr));
  1431.     if (item)
  1432.     {
  1433.     item -> item . type = POLYPOINT;
  1434.     item -> item . proximity = proximity;
  1435.  
  1436.     item -> lineWidth = 1;
  1437.     item -> nVertices = nVertices;
  1438.     for (k = 0; k < nVertices; ++k)
  1439.     {
  1440.         item -> vertices[k] = vertices[k];
  1441.     }
  1442.     AppendItemToPicture((PicPtr) pic, (PicItemPtr) item);
  1443.     return item;
  1444.     }
  1445.     else
  1446.     {
  1447.     return 0;
  1448.     }
  1449. }
  1450.  
  1451. #ifdef PROTO
  1452. FrustumPtr AppendFrustumToPicture(ObjPtr pic, float end1[3], float rad1,
  1453.         float end2[3], float rad2, int colorIndex)
  1454. #else
  1455. FrustumPtr AppendFrustumToPicture(pic, end1, rad1, end2, rad2, colorIndex)
  1456. ObjPtr pic;
  1457. float end1[3];
  1458. float rad1;
  1459. float end2[3];
  1460. float rad2;
  1461. int colorIndex;
  1462. #endif
  1463. /*Appends a conical frustum with endpoints end1 and end2 and radii rad1 and
  1464.   rad2 to picture pic*/
  1465. {
  1466.     FrustumPtr item;
  1467.     int k;
  1468.  
  1469.     item = newp(Frustum);
  1470.     if (item)
  1471.     {
  1472.     item -> item . type = FRUSTUM;
  1473.     item -> rad1 = rad1;
  1474.     item -> rad2 = rad2;
  1475.     item -> colorIndex = colorIndex;
  1476.     for (k = 0; k < 3; ++k)
  1477.     {
  1478.         item -> end1[k] = end1[k];
  1479.         item -> end2[k] = end2[k];
  1480.     }
  1481.     AppendItemToPicture((PicPtr) pic, (PicItemPtr) item);
  1482.     return item;
  1483.     }
  1484.     else
  1485.     {
  1486.     return 0;
  1487.     }
  1488. }
  1489.  
  1490. #ifdef PROTO
  1491. SpherePtr AppendSphereToPicture(ObjPtr pic, float center[3], float radius, int colorIndex)
  1492. #else
  1493. SpherePtr AppendSphereToPicture(pic, center, radius, colorIndex)
  1494. ObjPtr pic;
  1495. float center[3];
  1496. float radius;
  1497. int colorIndex;
  1498. #endif
  1499. /*Appends a sphere with center center and radius radius to pic*/
  1500. {
  1501.     SpherePtr item;
  1502.     int k;
  1503.  
  1504.     item = newp(Sphere);
  1505.     if (item)
  1506.     {
  1507.     item -> item . type = SPHERE;
  1508.     item -> radius = radius;
  1509.     item -> centerVertex = NewVertex(pic, 0);
  1510.     item -> centerVertex -> colorIndex = colorIndex;
  1511.     for (k = 0; k < 3; ++k)
  1512.     {
  1513.         item -> centerVertex -> position[k] = center[k];
  1514.     }
  1515.     AppendItemToPicture((PicPtr) pic, (PicItemPtr) item);
  1516.     return item;
  1517.     }
  1518.     else
  1519.     {
  1520.     return 0;
  1521.     }
  1522. }
  1523.  
  1524. static float curCenter[3];    /*Current center*/
  1525. static float curRadius;        /*Current radius*/
  1526. static int curSub;        /*Current number of subdivisions*/
  1527. static int curNSides;        /*Current number of sides*/
  1528.  
  1529. #ifdef GRAPHICS
  1530. void DrawQuadrant(r1, r2, r3, level)
  1531. float r1[3];
  1532. float r2[3];
  1533. float r3[3];
  1534. int level;
  1535. /*Draws a quadrant of sphere at center curCenter with radius curRadius given 
  1536.   radial normal vectors r1, r2, and r3, using current color table, at recursion 
  1537.   level level.  Assumes that the appropriate color table is current*/
  1538. {
  1539.     if (level >= SPHERESUB)
  1540.     {
  1541.     /*Maximum number of subdivisions has been reached*/
  1542.     float v1[3], v2[3], v3[3];
  1543.     v1[0] = curCenter[0] + r1[0] * curRadius;
  1544.     v1[1] = curCenter[1] + r1[1] * curRadius;
  1545.     v1[2] = curCenter[2] + r1[2] * curRadius;
  1546.     v2[0] = curCenter[0] + r2[0] * curRadius;
  1547.     v2[1] = curCenter[1] + r2[1] * curRadius;
  1548.     v2[2] = curCenter[2] + r2[2] * curRadius;
  1549.     v3[0] = curCenter[0] + r3[0] * curRadius;
  1550.     v3[1] = curCenter[1] + r3[1] * curRadius;
  1551.     v3[2] = curCenter[2] + r3[2] * curRadius;
  1552.  
  1553.         if (rgbp)
  1554.         {
  1555.             bgnpolygon();
  1556.         N3F(r1);
  1557.         v3f(v1);
  1558.         N3F(r2);
  1559.         v3f(v2);
  1560.         N3F(r3);
  1561.         v3f(v3);
  1562.         endpolygon();
  1563.         }
  1564.     else
  1565.         {
  1566.         bgnpolygon();
  1567.         SetRealColor(r1[0]);
  1568.         v3f(v1);
  1569.         SetRealColor(r2[0]);
  1570.         v3f(v2);
  1571.         SetRealColor(r3[0]);
  1572.         v3f(v3);
  1573.             endpolygon();
  1574.         }
  1575.     }
  1576.     else
  1577.     {
  1578.     /*Do another subdivision*/
  1579.     float r12[3], r23[3], r31[3];    /*Inner triangle subdivisions*/
  1580.     r12[0] = (r1[0] + r2[0]);
  1581.     r12[1] = (r1[1] + r2[1]);
  1582.     r12[2] = (r1[2] + r2[2]);
  1583.     r23[0] = (r2[0] + r3[0]);
  1584.     r23[1] = (r2[1] + r3[1]);
  1585.     r23[2] = (r2[2] + r3[2]);
  1586.     r31[0] = (r3[0] + r1[0]);
  1587.     r31[1] = (r3[1] + r1[1]);
  1588.     r31[2] = (r3[2] + r1[2]);
  1589.     NORMALIZE(r12);
  1590.     NORMALIZE(r23);
  1591.     NORMALIZE(r31);
  1592.  
  1593.     /*Draw the subdivisions*/
  1594.     DrawQuadrant(r1, r12, r31, level + 1);
  1595.     DrawQuadrant(r12, r2, r23, level + 1);
  1596.     DrawQuadrant(r23, r3, r31, level + 1);
  1597.     DrawQuadrant(r12, r23, r31, level + 1);
  1598.     }
  1599. }
  1600. #endif
  1601.  
  1602. static Bool formsAreEqual;
  1603.  
  1604. #ifdef PROTO
  1605. void UnColorPicture(ObjPtr pic)
  1606. #else
  1607. void UnColorPicture(pic)
  1608. ObjPtr pic;
  1609. #endif
  1610. /*Uncolors picture pic*/
  1611. {
  1612.     PicItemPtr curItem;
  1613.     ObjPtr repObj;
  1614.  
  1615.     curItem = ((PicPtr) pic) -> items;
  1616.  
  1617.     while (curItem)
  1618.     {
  1619.     curItem = curItem -> next;
  1620.     }
  1621. }
  1622.  
  1623. #ifdef PROTO
  1624. void ColorItemByObject(PicItemPtr curItem,ObjPtr colorObj, Bool interpolate)
  1625. #else
  1626. void ColorItemByObject(curItem, colorObj, interpolate)
  1627. PicItemPtr curItem;
  1628. ObjPtr colorObj;
  1629. Bool interpolate;
  1630. #endif
  1631. /*Colors item curItem by colorObj*/
  1632. {
  1633.     long k;
  1634.     long nVertices;
  1635.     VertexPtr *vertices;
  1636.  
  1637.     switch(curItem -> type)
  1638.     {
  1639.     case POLYGON:
  1640.     case PLANARPOLYGON:
  1641.     case POLYLINE:
  1642.     case POLYPOINT:
  1643.         nVertices = ((PolyPtr) curItem) -> nVertices;
  1644.         vertices = ((PolyPtr) curItem) -> vertices;
  1645.         break;
  1646.     case POLYGONS:
  1647.         ColorItemsByObject((PicItemPtr) ((PolysPtr) curItem) -> polygons, 
  1648.             colorObj, interpolate);
  1649.         return;
  1650.         break;
  1651.     case RECTMESH:
  1652.         {
  1653.         int i, j;
  1654.         real sample;
  1655.         int index;
  1656.         long offset;
  1657.         real position[3];
  1658.  
  1659.  
  1660.         vertices = ((RectMeshPtr) curItem) -> vertices;
  1661.         if (((RectMeshPtr) curItem) -> inCenter)
  1662.         {
  1663.             for (i = 0; i < ((RectMeshPtr) curItem) -> xDim - 1; ++i)
  1664.             {
  1665.             for (j = 0; j < ((RectMeshPtr) curItem) -> yDim - 1; ++j)
  1666.             {
  1667.                 offset = RECTMESHCENTER((RectMeshPtr) curItem, i, j);
  1668.                 position[0] = vertices[offset] -> position[0];
  1669.                 position[1] = vertices[offset] -> position[1];
  1670.                 position[2] = vertices[offset] -> position[2];
  1671.  
  1672.                 sample = SampleSpatScalar(FIELD1, FIELD2,
  1673.                 3, position, interpolate);
  1674.  
  1675.                 index = GetRealColorIndex(sample);
  1676.                 vertices[offset] -> colorIndex = index;
  1677.             }
  1678.             }
  1679.             InterpRectVertices((RectMeshPtr) curItem);
  1680.         }
  1681.         else
  1682.         {
  1683.             for (i = 0; i < ((RectMeshPtr) curItem) -> xDim; ++i)
  1684.             {
  1685.             for (j = 0; j < ((RectMeshPtr) curItem) -> yDim; ++j)
  1686.             {
  1687.                 offset = RECTMESHVERTEX((RectMeshPtr) curItem, i, j);
  1688.  
  1689.                 position[0] = vertices[offset] -> position[0];
  1690.                 position[1] = vertices[offset] -> position[1];
  1691.                 position[2] = vertices[offset] -> position[2];
  1692.  
  1693.                 sample = SampleSpatScalar(FIELD1, FIELD2,
  1694.                 3, position, interpolate);
  1695.  
  1696.                 index = GetRealColorIndex(sample);
  1697.                 vertices[offset] -> colorIndex = index;
  1698.             }
  1699.             }
  1700.             InterpRectCenters((RectMeshPtr) curItem);
  1701.         }
  1702.         }
  1703.         return;
  1704.         break;
  1705.     default:
  1706.         return;
  1707.     }
  1708.  
  1709.     if (formsAreEqual && curItem -> flags & PF_CANONVERTICES)
  1710.     {
  1711.     int nTraversalDims;        /*Number of dimensions to traverse*/
  1712.     int whichDim;            /*Dimension counter*/
  1713.     long *traversalDims = 0;    /*Dimensions of the dataset to traverse*/
  1714.     long *index = 0;        /*Counting index*/
  1715.     long nNodes;            /*# Total nodes in the dataset*/
  1716.     int nComponents;        /*# components of data form*/
  1717.     real sample;
  1718.  
  1719.     /*Get the information on traversing the dataset*/
  1720.     nTraversalDims = CountTraversalDims(FORMFIELD);
  1721.     if (nTraversalDims)
  1722.     {
  1723.         traversalDims = (long *) Alloc(sizeof(long) * nTraversalDims);
  1724.         index = (long *) Alloc(sizeof(long) * nTraversalDims);
  1725.     }
  1726.     else
  1727.     {
  1728.         index = (long *) Alloc(sizeof(long));
  1729.     }
  1730.     GetTraversalDims(FORMFIELD, traversalDims);
  1731.  
  1732.     /*Calculate the number of nodes*/
  1733.     nNodes = 1;
  1734.     for (whichDim = 0; whichDim < nTraversalDims; ++whichDim)
  1735.     {
  1736.         if (traversalDims[whichDim] > 0)
  1737.         {
  1738.         nNodes *= traversalDims[whichDim];
  1739.         }
  1740.     }
  1741.  
  1742.     /*Color as many vertices as we have nodes*/
  1743.  
  1744.     /*Zero the index*/
  1745.     for (whichDim = 0; whichDim < nTraversalDims; ++whichDim)
  1746.     {
  1747.         index[whichDim] = 0;
  1748.     }
  1749.  
  1750.     /*Traverse all the points*/
  1751.     k = 0;
  1752.     do
  1753.     {
  1754.         /*Sample the location at a point*/
  1755.         sample = SelectFieldScalar(FIELD1, index);
  1756.         vertices[k] -> colorIndex = GetRealColorIndex(sample);
  1757.         ++k;
  1758.  
  1759.         /*Advance to next point*/
  1760.         for (whichDim = 0; whichDim < nTraversalDims; ++whichDim)
  1761.         {
  1762.         if (traversalDims[whichDim] > 0)
  1763.         {
  1764.             if ((++index[whichDim]) >= traversalDims[whichDim])
  1765.             {
  1766.             index[whichDim] = 0;
  1767.             }
  1768.             else
  1769.             {
  1770.             break;
  1771.             }
  1772.         }
  1773.         }
  1774.     } while (whichDim < nTraversalDims); /*Break is based on advance*/
  1775.  
  1776.     /*Free up temporary storage*/
  1777.     SAFEFREE(traversalDims);
  1778.     SAFEFREE(index);
  1779.     }
  1780.     else
  1781.     {
  1782.     real position[3];
  1783.     real sample;
  1784.     int index;
  1785.     int j;
  1786.     /*Make it colored*/
  1787.     for (k = 0; k < nVertices; ++k)
  1788.     {
  1789.     
  1790.         position[0] = vertices[k] -> position[0];
  1791.         position[1] = vertices[k] -> position[1];
  1792.         position[2] = vertices[k] -> position[2];
  1793.     
  1794.         sample = SampleSpatScalar(FIELD1, FIELD2,
  1795.                 3, position, interpolate);
  1796.     
  1797.         index = GetRealColorIndex(sample);
  1798.         vertices[k] -> colorIndex = index;
  1799.     }
  1800.     }
  1801. }
  1802.  
  1803. #ifdef PROTO
  1804. void ColorItemWithIndex(PicItemPtr curItem, int index)
  1805. #else
  1806. void ColorItemWithIndex(curItem, index)
  1807. PicItemPtr curItem;
  1808. int index;
  1809. #endif
  1810. /*Colors item curItem with index*/
  1811. {
  1812.     long k;
  1813.     long nVertices;
  1814.     VertexPtr *vertices;
  1815.  
  1816.     switch(curItem -> type)
  1817.     {
  1818.         case POLYGON:
  1819.         case PLANARPOLYGON:
  1820.         case POLYLINE:
  1821.         nVertices = ((PolyPtr) curItem) -> nVertices;
  1822.         vertices = ((PolyPtr) curItem) -> vertices;
  1823.         break;
  1824.         case POLYGONS:
  1825.         ColorItemsWithIndex((PicItemPtr) ((PolysPtr) curItem) -> polygons, 
  1826.             index);
  1827.         return;
  1828.         break;
  1829.         case RECTMESH:
  1830.         {
  1831.             int i, j;
  1832.             real sample;
  1833.             long offset;
  1834.  
  1835.             vertices = ((RectMeshPtr) curItem) -> vertices;
  1836.             if (((RectMeshPtr) curItem) -> inCenter)
  1837.             {
  1838.             for (i = 0; i < ((RectMeshPtr) curItem) -> xDim - 1; ++i)
  1839.             {
  1840.                 for (j = 0; j < ((RectMeshPtr) curItem) -> yDim - 1; ++j)
  1841.                 {
  1842.                 offset = RECTMESHCENTER((RectMeshPtr) curItem, i, j);
  1843.  
  1844.                 vertices[offset] -> colorIndex = index;
  1845.                 }
  1846.             }
  1847.             InterpRectVertices((RectMeshPtr) curItem);
  1848.             }
  1849.             else
  1850.             {
  1851.             for (i = 0; i < ((RectMeshPtr) curItem) -> xDim; ++i)
  1852.             {
  1853.                 for (j = 0; j < ((RectMeshPtr) curItem) -> yDim; ++j)
  1854.                 {
  1855.                 offset = RECTMESHVERTEX((RectMeshPtr) curItem, i, j);
  1856.  
  1857.                 vertices[offset] -> colorIndex = index;
  1858.                 }
  1859.             }
  1860.             InterpRectCenters((RectMeshPtr) curItem);
  1861.             }
  1862.         }
  1863.         return;
  1864.         break;
  1865.         default:
  1866.         return;
  1867.     }
  1868.  
  1869.     /*Make it colored*/
  1870.     for (k = 0; k < nVertices; ++k)
  1871.     {
  1872.         vertices[k] -> colorIndex = index;
  1873.     }
  1874. }
  1875.  
  1876. #ifdef PROTO
  1877. void ColorItemsByObject(PicItemPtr curItem,ObjPtr colorObj, Bool interpolate)
  1878. #else
  1879. void ColorItemsByObject(curItem, colorObj, interpolate)
  1880. PicItemPtr curItem;
  1881. ObjPtr colorObj;
  1882. Bool interpolate;
  1883. #endif
  1884. /*Colors items at curItem by colorObj*/
  1885. {
  1886.     ObjPtr repObj;
  1887.     ObjPtr colors;
  1888.     long k;
  1889.  
  1890.     MakeVar(colorObj, CPALETTE);
  1891.     colors = GetPaletteVar("ColorItemsByObject", colorObj, CPALETTE);
  1892.     if (!colors) return;
  1893.     SetPalette(colors);
  1894.  
  1895.     while (curItem)
  1896.     {
  1897.     ColorItemByObject(curItem, colorObj, interpolate);
  1898.  
  1899.     curItem = curItem -> next;
  1900.     }
  1901. }
  1902.  
  1903. #ifdef PROTO
  1904. void ColorItemsWithIndex(PicItemPtr curItem, int index)
  1905. #else
  1906. void ColorItemsWithIndex(curItem, index)
  1907. PicItemPtr curItem;
  1908. int index;
  1909. #endif
  1910. /*Colors items starting at curItem with index*/
  1911. {
  1912.     ObjPtr repObj;
  1913.     ObjPtr colors;
  1914.     long k;
  1915.  
  1916.     while (curItem)
  1917.     {
  1918.     ColorItemWithIndex(curItem, index);
  1919.  
  1920.     curItem = curItem -> next;
  1921.     }
  1922. }
  1923.  
  1924. #ifdef PROTO
  1925. void ColorPictureByObject(ObjPtr pic,ObjPtr colorObj, Bool interpolate)
  1926. #else
  1927. void ColorPictureByObject(pic, colorObj, interpolate)
  1928. ObjPtr pic;
  1929. ObjPtr colorObj;
  1930. Bool interpolate;
  1931. #endif
  1932. /*Colors picture pic by colorObj.  if interpolate, interpolates on lookup*/
  1933. {
  1934.     register VertexPtr runner;
  1935.     register VertexPtr last = NULL;
  1936.     int nTraversalDims;        /*Number of dimensions to traverse*/
  1937.     int whichDim;            /*Dimension counter*/
  1938.     long *traversalDims = 0;    /*Dimensions of the dataset to traverse*/
  1939.     long *index = 0;        /*Counting index*/
  1940.     long nNodes;            /*# Total nodes in the dataset*/
  1941.     int nComponents;        /*# components of data form*/
  1942.     real sample;
  1943.  
  1944.     ObjPtr mainDataset = NULLOBJ;
  1945.  
  1946.     SetCurField(FIELD1, colorObj);
  1947.     SetCurForm(FIELD2, colorObj);
  1948.  
  1949.     formsAreEqual = false;
  1950.  
  1951.     mainDataset = GetVar(pic, MAINDATASET);
  1952.  
  1953.     if (mainDataset && IsDataset(mainDataset))
  1954.     {
  1955.     SetCurForm(FORMFIELD, mainDataset);
  1956.     if (IdenticalFields(FORMFIELD, FIELD2))
  1957.     {
  1958.         formsAreEqual = true;
  1959.     }
  1960.     }
  1961.  
  1962.     /*Make all vertices not colored*/
  1963.     runner = ((PicPtr) pic) -> vertices;
  1964.     while (runner)
  1965.     {
  1966.     runner -> flags &= ~VF_COLORED;
  1967.     runner = runner -> next;
  1968.     }
  1969.  
  1970.     /*Create information for the canonical group*/
  1971.     if (formsAreEqual)
  1972.     {
  1973.     nTraversalDims = CountTraversalDims(FORMFIELD);
  1974.     if (nTraversalDims)
  1975.     {
  1976.         traversalDims = (long *) Alloc(sizeof(long) * nTraversalDims);
  1977.         index = (long *) Alloc(sizeof(long) * nTraversalDims);
  1978.     }
  1979.     else
  1980.     {
  1981.         index = (long *) Alloc(sizeof(long));
  1982.     }
  1983.     GetTraversalDims(FORMFIELD, traversalDims);
  1984.  
  1985.     /*Calculate the number of nodes*/
  1986.     nNodes = 1;
  1987.     for (whichDim = 0; whichDim < nTraversalDims; ++whichDim)
  1988.     {
  1989.         if (traversalDims[whichDim] > 0)
  1990.         {
  1991.         nNodes *= traversalDims[whichDim];
  1992.         }
  1993.     }
  1994.     }
  1995.  
  1996.     runner = ((PicPtr) pic) -> vertices;
  1997.     while (runner)
  1998.     {
  1999.     if (!(runner -> flags & VF_COLORED))
  2000.     {
  2001.         runner -> flags |= VF_COLORED;
  2002.  
  2003.         if (formsAreEqual && runner -> flags & VF_FIRSTCANON)
  2004.         {
  2005.         /*Begin a canonical group*/
  2006.     
  2007.         /*Zero the index*/
  2008.         for (whichDim = 0; whichDim < nTraversalDims; ++whichDim)
  2009.         {
  2010.             index[whichDim] = 0;
  2011.         }
  2012.         }
  2013.  
  2014.         if (formsAreEqual && runner -> flags & VF_NEXTCANON)
  2015.         {
  2016.         /*Advance to next point*/
  2017.         for (whichDim = 0; whichDim < nTraversalDims; ++whichDim)
  2018.         {
  2019.             if (traversalDims[whichDim] > 0)
  2020.             {
  2021.             if ((++index[whichDim]) >= traversalDims[whichDim])
  2022.             {
  2023.                 index[whichDim] = 0;
  2024.             }
  2025.             else
  2026.             {
  2027.                 break;
  2028.             }
  2029.             }
  2030.         }
  2031.         if (whichDim >= nTraversalDims)
  2032.         {
  2033.             /*Wraparound*/
  2034.             for (whichDim = 0; whichDim < nTraversalDims; ++whichDim)
  2035.             {
  2036.             index[whichDim] = 0;
  2037.             }
  2038.         }    
  2039.         }
  2040.  
  2041.         if (last && (runner -> flags & VF_SAMEPLACE))
  2042.         {
  2043.         runner -> colorIndex = last -> colorIndex;
  2044.         }
  2045.         else if (formsAreEqual &&
  2046.         ((runner -> flags & VF_NEXTCANON) ||
  2047.          (runner -> flags & VF_FIRSTCANON)))
  2048.         {
  2049.         /*Sample from dataform*/
  2050.         sample = SelectFieldScalar(FIELD1, index);
  2051.         runner -> colorIndex = GetRealColorIndex(sample);
  2052.         }
  2053.         else
  2054.         {
  2055.         /*Sample arbitrarily*/
  2056.  
  2057.         sample = SampleSpatScalar(FIELD1, FIELD2,
  2058.                 3, runner -> position, interpolate);
  2059.     
  2060.         runner -> colorIndex = GetRealColorIndex(sample);
  2061.         }
  2062.     }
  2063.     last = runner;
  2064.     runner = runner -> next;
  2065.     }
  2066.  
  2067.     if (formsAreEqual)
  2068.     {
  2069.     /*Free up temporary storage*/
  2070.     SAFEFREE(traversalDims);
  2071.     SAFEFREE(index);
  2072.     }
  2073. }
  2074.  
  2075. #ifdef PROTO
  2076. void PickCanonicalPictureVertices(ObjPtr pic)
  2077. #else
  2078. void PickCanonicalPictureVertices(pic)
  2079. ObjPtr pic;
  2080. #endif
  2081. /*Picks the vertices in a picture*/
  2082. {
  2083.     VertexPtr runner;
  2084.     long curVertex = 0;
  2085.     Bool inCanon = false;
  2086.  
  2087.     runner = ((PicPtr) pic) -> vertices;
  2088.     while (runner)
  2089.     {
  2090. #if 0
  2091.     if (!inCanon)
  2092.     {
  2093.         PickVertex(curVertex++);
  2094.     }
  2095.     else if ((runner -> flags & VF_NEXTCANON) || !inCanon)
  2096.     {
  2097.         ++curVertex;
  2098.     }
  2099.     if (runner -> flags & VF_FIRSTCANON)
  2100.     {
  2101.         inCanon = true;
  2102.         curVertex = 0;
  2103.         PickVertex(curVertex);
  2104.     }
  2105. #endif
  2106.     bgnpoint();
  2107.     v3f(runner -> position);
  2108.     endpoint();
  2109.     runner = runner -> next;
  2110.     }
  2111. }
  2112.  
  2113. #ifdef PROTO
  2114. void DeformPictureByObject(ObjPtr pic)
  2115. #else
  2116. void DeformPictureByObject(pic)
  2117. ObjPtr pic;
  2118. #endif
  2119. /*Deforms picture pic.
  2120.  
  2121.   ASSUMES that SetupDeformation has been done on the visualization object
  2122. */
  2123. {
  2124.     register VertexPtr runner;
  2125.  
  2126.     runner = ((PicPtr) pic) -> vertices;
  2127.     while (runner)
  2128.     {
  2129.     runner -> flags &= ~VF_DEFORMED;
  2130.     runner = runner -> next;
  2131.     }
  2132.  
  2133.     runner = ((PicPtr) pic) -> vertices;
  2134.     while (runner)
  2135.     {
  2136.     if (!(runner -> flags & VF_DEFORMED))
  2137.     {
  2138.         runner -> flags |= VF_DEFORMED;
  2139.         DEFORMVERTEX(runner);
  2140.     }
  2141.     runner = runner -> next;
  2142.     }
  2143.  
  2144.     CalcPictureNormals(pic);
  2145. }
  2146.  
  2147. #ifdef PROTO
  2148. void CalcPolyNormals(PolyPtr poly)
  2149. #else
  2150. void CalcPolyNormals(poly)
  2151. PolyPtr poly;
  2152. #endif
  2153. /*Calculates the normals in a polygon*/
  2154. {
  2155.     float x[3], nml[3], v1[3], v2[3];
  2156.     register float mag;
  2157.     register int i, p, m, n;
  2158.  
  2159.     /*Set up z normal, just in case*/
  2160.     nml[0] = 0.0;
  2161.     nml[1] = 0.0;
  2162.     nml[2] = 1.0;
  2163.  
  2164.     /*Go around, starting at 1 for robustness*/
  2165.     for (i = 1; i <= poly -> nVertices; ++i)
  2166.     {
  2167.     p = i - 1;
  2168.     m = i % (poly -> nVertices);
  2169.     n = (i + 1) % (poly -> nVertices);
  2170.     
  2171.     v1[0] = poly -> vertices[p] -> position[0] -
  2172.         poly -> vertices[m] -> position[0];
  2173.     v1[1] = poly -> vertices[p] -> position[1] -
  2174.         poly -> vertices[m] -> position[1];
  2175.     v1[2] = poly -> vertices[p] -> position[2] -
  2176.         poly -> vertices[m] -> position[2];
  2177.  
  2178.     v2[0] = poly -> vertices[n] -> position[0] -
  2179.         poly -> vertices[m] -> position[0];
  2180.     v2[1] = poly -> vertices[n] -> position[1] -
  2181.         poly -> vertices[m] -> position[1];
  2182.     v2[2] = poly -> vertices[n] -> position[2] -
  2183.         poly -> vertices[m] -> position[2];
  2184.  
  2185.     CROSS(v2, v1, x);
  2186.  
  2187.     mag = MAG3(x);
  2188.  
  2189.     if (mag > 0.0)
  2190.     {
  2191.         /*Normal stuff*/
  2192.         mag = 1.0 / mag;
  2193.         nml[0] = x[0] * mag;
  2194.         nml[1] = x[1] * mag;
  2195.         nml[2] = x[2] * mag;
  2196.     }
  2197.     poly -> vertices[m] -> normal[0] += nml[0];
  2198.     poly -> vertices[m] -> normal[1] += nml[1];
  2199.     poly -> vertices[m] -> normal[2] += nml[2];
  2200.     }
  2201. }
  2202.  
  2203. #ifdef PROTO
  2204. void CalcPolytriNormals(PolyPtr poly)
  2205. #else
  2206. void CalcPolytriNormals(poly)
  2207. PolyPtr poly;
  2208. #endif
  2209. /*Calculates the normals in a triangular mesh strip*/
  2210. {
  2211.     float x[3], v1[3], v2[3];
  2212.     register float mag;
  2213.     register int i;
  2214.  
  2215.     i = 0;
  2216.     while (i < poly -> nVertices - 2)
  2217.     {
  2218.     /*Do a clockwise panel*/
  2219.     v1[0] = poly -> vertices[i + 1] -> position[0] -
  2220.         poly -> vertices[i] -> position[0];
  2221.     v1[1] = poly -> vertices[i + 1] -> position[1] -
  2222.         poly -> vertices[i] -> position[1];
  2223.     v1[2] = poly -> vertices[i + 1] -> position[2] -
  2224.         poly -> vertices[i] -> position[2];
  2225.  
  2226.     v2[0] = poly -> vertices[i + 2] -> position[0] -
  2227.         poly -> vertices[i] -> position[0];
  2228.     v2[1] = poly -> vertices[i + 2] -> position[1] -
  2229.         poly -> vertices[i] -> position[1];
  2230.     v2[2] = poly -> vertices[i + 2] -> position[2] -
  2231.         poly -> vertices[i] -> position[2];
  2232.  
  2233.     CROSS(v1, v2, x);
  2234.  
  2235.     mag = MAG3(x);
  2236.     if (mag > 0.0)
  2237.     {
  2238.         /*Normal stuff*/
  2239.         mag = 1.0 / mag;
  2240.         poly -> vertices[i] -> normal[0] += x[0] * mag;
  2241.         poly -> vertices[i] -> normal[1] += x[1] * mag;
  2242.         poly -> vertices[i] -> normal[2] += x[2] * mag;
  2243.  
  2244.         poly -> vertices[i + 1] -> normal[0] += x[0] * mag;
  2245.         poly -> vertices[i + 1] -> normal[1] += x[1] * mag;
  2246.         poly -> vertices[i + 1] -> normal[2] += x[2] * mag;
  2247.  
  2248.         poly -> vertices[i + 2] -> normal[0] += x[0] * mag;
  2249.         poly -> vertices[i + 2] -> normal[1] += x[1] * mag;
  2250.         poly -> vertices[i + 2] -> normal[2] += x[2] * mag;
  2251.     }
  2252.  
  2253.     ++i;
  2254.  
  2255.     if (i < poly -> nVertices - 2)
  2256.     {
  2257.          /*Do a counterclockwise panel*/
  2258.         v1[0] = poly -> vertices[i + 2] -> position[0] -
  2259.             poly -> vertices[i] -> position[0];
  2260.         v1[1] = poly -> vertices[i + 2] -> position[1] -
  2261.             poly -> vertices[i] -> position[1];
  2262.         v1[2] = poly -> vertices[i + 2] -> position[2] -
  2263.             poly -> vertices[i] -> position[2];
  2264.     
  2265.         v2[0] = poly -> vertices[i + 1] -> position[0] -
  2266.             poly -> vertices[i] -> position[0];
  2267.         v2[1] = poly -> vertices[i + 1] -> position[1] -
  2268.             poly -> vertices[i] -> position[1];
  2269.         v2[2] = poly -> vertices[i + 1] -> position[2] -
  2270.             poly -> vertices[i] -> position[2];
  2271.     
  2272.         CROSS(v1, v2, x);
  2273.         mag = MAG3(x);
  2274.         if (mag > 0.0)
  2275.         {
  2276.         /*Normal stuff*/
  2277.         mag = 1.0 / mag;
  2278.         poly -> vertices[i] -> normal[0] += x[0] * mag;
  2279.         poly -> vertices[i] -> normal[1] += x[1] * mag;
  2280.         poly -> vertices[i] -> normal[2] += x[2] * mag;
  2281.     
  2282.         poly -> vertices[i + 1] -> normal[0] += x[0] * mag;
  2283.         poly -> vertices[i + 1] -> normal[1] += x[1] * mag;
  2284.         poly -> vertices[i + 1] -> normal[2] += x[2] * mag;
  2285.     
  2286.         poly -> vertices[i + 2] -> normal[0] += x[0] * mag;
  2287.         poly -> vertices[i + 2] -> normal[1] += x[1] * mag;
  2288.         poly -> vertices[i + 2] -> normal[2] += x[2] * mag;
  2289.         }
  2290.     
  2291.         ++i;
  2292.     }
  2293.     }
  2294. }
  2295.  
  2296. #ifdef PROTO
  2297. void CalcPictureNormals(ObjPtr pic)
  2298. #else
  2299. void CalcPictureNormals(pic)
  2300. ObjPtr pic;
  2301. #endif
  2302. /*Calculates the normals within pic*/
  2303. {
  2304.     PicItemPtr curItem;
  2305.     VertexPtr vertices;
  2306.  
  2307.     /*Go through and zero the normals*/
  2308.     vertices = ((PicPtr) pic) -> vertices;
  2309.     while (vertices)
  2310.     {
  2311.     vertices -> normal[0] = 0.0;
  2312.     vertices -> normal[1] = 0.0;
  2313.     vertices -> normal[2] = 0.0;
  2314.     vertices = vertices -> next;
  2315.     }
  2316.  
  2317.     curItem = ((PicPtr) pic) -> items;
  2318.     while (curItem)
  2319.     {
  2320.     switch(curItem -> type)
  2321.     {
  2322.         case POLYGON:
  2323.         case PLANARPOLYGON:
  2324.         CalcPolyNormals((PolyPtr) curItem);
  2325.         break;
  2326.         case POLYTRI:
  2327.         CalcPolytriNormals((PolyPtr) curItem);
  2328.         break;
  2329.         case POLYGONS:
  2330.         {
  2331.             PolyPtr runner;
  2332.             runner = ((PolysPtr) ((PicPtr) pic) -> items) -> polygons;
  2333.             while (runner)
  2334.             {
  2335.             CalcPolyNormals(runner);
  2336.             runner = (PolyPtr) runner -> item . next;
  2337.             }
  2338.         }
  2339.         break;
  2340.         case RECTMESH:
  2341.         CalcRectNormals((RectMeshPtr) curItem);
  2342.         break;
  2343.     }
  2344.     curItem = curItem -> next;
  2345.     }
  2346.  
  2347.     /*Go through and NORMALIZE the normals*/
  2348.     vertices = ((PicPtr) pic) -> vertices;
  2349.     while (vertices)
  2350.     {
  2351.     double f;
  2352.     f = MAG3(vertices -> normal);
  2353.     if (f > 0.0)
  2354.     {
  2355.         f = 1.0 / f;
  2356.         vertices -> normal[0] *= f;
  2357.         vertices -> normal[1] *= f;
  2358.         vertices -> normal[2] *= f;
  2359.     }
  2360.     else
  2361.     {
  2362.         vertices -> normal[2] = 1.0;
  2363.     }
  2364.     vertices = vertices -> next;
  2365.     }
  2366.  
  2367. }
  2368.  
  2369. #ifdef GRAPHICS
  2370. /*Shading models*/
  2371. int shadeModels[2][4][3] =
  2372.     {
  2373.     {{    FLAT,    FLAT, GOURAUD},
  2374.      {    FLAT,    FLAT, GOURAUD},
  2375.      { GOURAUD,    FLAT, GOURAUD},
  2376.      { GOURAUD, GOURAUD, GOURAUD}},
  2377.     {{    FLAT,    FLAT, GOURAUD},
  2378.      {    FLAT,    FLAT, GOURAUD},
  2379.      { GOURAUD, GOURAUD, GOURAUD},
  2380.      { GOURAUD, GOURAUD, GOURAUD}}
  2381.     };
  2382.  
  2383. #define PrepareToDrawC                        \
  2384.     color(curBeg + curNColors - 4);
  2385.     
  2386. #define PrepareToDrawRGB                        \
  2387.     C3S(curColors[curNColors - 4]);
  2388.  
  2389. #define PrepareToDrawCDepthCue                    \
  2390.     lshaderange(curBeg + 2, curBeg + curNColors - 4, curZMin, curZMax);
  2391.  
  2392. #define PrepareToDrawRGBDepthCue                    \
  2393.     lRGBrange(0,        \
  2394.           0,        \
  2395.           0,        \
  2396.           curColors[curNColors - 4][0],        \
  2397.           curColors[curNColors - 4][1],        \
  2398.           curColors[curNColors - 4][2], curZMin, curZMax);
  2399.  
  2400.  
  2401. float tN[3];
  2402.  
  2403. /*Traversal macros to make life a little easier*/
  2404.  
  2405. /*Polygon traversal macro.  Decomposes simply into triangles*/
  2406. #define TRAVERSEPOLY {                            \
  2407.     register VertexPtr *v1, *v2;                    \
  2408.     v1 = ((PolyPtr) curItem) -> vertices;                \
  2409.         v2 = ((PolyPtr) curItem) -> vertices +             \
  2410.         (((PolyPtr) curItem) -> nVertices - 1);            \
  2411.     bgntmesh();                                \
  2412.     P(v1, ((PolyPtr) curItem) -> nVertices);                \
  2413.                                     \
  2414.     while (v2 >= v1)                            \
  2415.     {                                    \
  2416.     /*Emit v1 and increment*/                    \
  2417.     V(v1);                                \
  2418.     ++v1;                                \
  2419.     if (v2 >= v1)                            \
  2420.     {                                \
  2421.         /*Emit v2 and decrement*/                    \
  2422.         V(v2);                            \
  2423.         --v2;                            \
  2424.     }                                \
  2425.     }                                    \
  2426.     endtmesh();}
  2427.  
  2428. /*Polytri traversal macro.  */
  2429. #define TRAVERSEPOLYTRI {                        \
  2430.     register int k, n;                            \
  2431.     register VertexPtr *v1;                        \
  2432.     n = ((PolyPtr) curItem) -> nVertices;                \
  2433.     v1 = ((PolyPtr) curItem) -> vertices;                \
  2434.     bgntmesh();                                \
  2435.     P(v1, ((PolyPtr) curItem) -> nVertices);                \
  2436.                                     \
  2437.     for (k = 0; k < n; ++k)                        \
  2438.     {                                    \
  2439.     /*Emit v1 and increment*/                    \
  2440.     V(v1); ++v1;                            \
  2441.     }                                    \
  2442.     endtmesh();}
  2443.  
  2444. /*Planar traversal macro*/
  2445. #define TRAVERSEPLANARPOLY {                        \
  2446.     register VertexPtr *v1;                        \
  2447.     register int k;                            \
  2448.     v1 = ((PolyPtr) curItem) -> vertices;                \
  2449.                                     \
  2450.     bgnpolygon();                            \
  2451.     P(v1, ((PolyPtr) curItem) -> nVertices);                \
  2452.     for (k = 0; k < ((PolyPtr) curItem) -> nVertices; ++k)        \
  2453.     {                                    \
  2454.     /*Emit v1 and increment*/                    \
  2455.     V(v1);                                \
  2456.     ++v1;                                \
  2457.     }                                    \
  2458.     endpolygon();}
  2459.  
  2460. /*Polyline traversal macro*/
  2461. #define TRAVERSEPOLYLINE {                        \
  2462.     register VertexPtr *v1;                        \
  2463.     register int k;                            \
  2464.     v1 = ((PolyPtr) curItem) -> vertices;                \
  2465.                                     \
  2466.     bgnline();                                \
  2467.     P(v1, ((PolyPtr) curItem) -> nVertices);                \
  2468.     for (k = 0; k < ((PolyPtr) curItem) -> nVertices; ++k)        \
  2469.     {                                    \
  2470.     /*Emit v1 and increment*/                    \
  2471.     V(v1);                                \
  2472.     ++v1;                                \
  2473.     }                                    \
  2474.     endline();}
  2475.  
  2476. /*Polypoint traversal macro*/
  2477. #define TRAVERSEPOLYPOINT {                        \
  2478.     register VertexPtr *v1;                        \
  2479.     register int k;                            \
  2480.     v1 = ((PolyPtr) curItem) -> vertices;                \
  2481.                                     \
  2482.     bgnpoint();                                \
  2483.     P(v1, ((PolyPtr) curItem) -> nVertices);                \
  2484.     for (k = 0; k < ((PolyPtr) curItem) -> nVertices; ++k)        \
  2485.     {                                    \
  2486.     /*Emit v1 and increment*/                    \
  2487.     if (0 == ((*v1) -> flags & VF_DONTDRAW)) {V(v1)}            \
  2488.     ++v1;                                \
  2489.     }                                    \
  2490.     endpoint();                                \
  2491. }
  2492.  
  2493. /*Closed polyline traversal macro*/
  2494. #define TRAVERSECLOSEDPOLYLINE {                        \
  2495.     register VertexPtr *v1;                        \
  2496.     register int k;                            \
  2497.     v1 = ((PolyPtr) curItem) -> vertices;                \
  2498.                                     \
  2499.     bgnclosedline();                                \
  2500.     P(v1, ((PolyPtr) curItem) -> nVertices);                \
  2501.     for (k = 0; k < ((PolyPtr) curItem) -> nVertices; ++k)        \
  2502.     {                                    \
  2503.     /*Emit v1 and increment*/                    \
  2504.     V(v1);                                \
  2505.     ++v1;                                \
  2506.     }                                    \
  2507.     endclosedline();}
  2508.  
  2509. /*Closed polytri line traversal macro*/
  2510. #define TRAVERSECLOSEDPOLYTRI {                        \
  2511.     register VertexPtr *v1;                        \
  2512.     register int k;                            \
  2513.     v1 = ((PolyPtr) curItem) -> vertices;                \
  2514.                                     \
  2515.     bgnclosedline();                            \
  2516.     P(v1, ((PolyPtr) curItem) -> nVertices);                \
  2517.     V(v1);                                \
  2518.     k = 1; ++v1;                            \
  2519.     while (k < ((PolyPtr) curItem) -> nVertices)            \
  2520.     {                                    \
  2521.     V(v1);                                \
  2522.     v1 += 2;                            \
  2523.     k += 2;                                \
  2524.     } --k; --v1;                            \
  2525.     if (k < ((PolyPtr) curItem) -> nVertices) {k += 2; v1 += 2;}    \
  2526.     do                                    \
  2527.     {                                    \
  2528.     k -= 2;                                \
  2529.     v1 -= 2;                            \
  2530.     V(v1);                                \
  2531.     } while (k > 0);                            \
  2532.     endclosedline();}
  2533.  
  2534. /*Dots traversal macro*/
  2535. #define TRAVERSEDOTS    {                        \
  2536.     VertexPtr vertices;                            \
  2537.     vertices = ((PicPtr) pic) -> vertices;                \
  2538.     bgnpoint();                                \
  2539.     P(&vertices, 1);                            \
  2540.     while (vertices)                            \
  2541.     {                                    \
  2542.     if (0 == (vertices -> flags & VF_DONTDRAW)) {V(&vertices)}    \
  2543.     vertices = vertices -> next;                    \
  2544.     }                                    \
  2545.     endpoint();}
  2546.  
  2547. /*Wire frame rectangle traversal macro*/
  2548. #define TRAVERSEWRECTMESH                        \
  2549.     {                                    \
  2550.     register int i, j;                            \
  2551.     int xDim, yDim;                            \
  2552.     register VertexPtr *vertexPtr;                    \
  2553.     int nX, nY;                                \
  2554.                                     \
  2555.     vertexPtr = ((RectMeshPtr) curItem) -> vertices;            \
  2556.     xDim = ((RectMeshPtr) curItem) -> xDim;                \
  2557.     yDim = ((RectMeshPtr) curItem) -> yDim;                \
  2558.     nX = (2 * yDim - 1);                        \
  2559.     nY = 2;                                \
  2560.                                     \
  2561.     /*Draw the fast moving axes*/                    \
  2562.     for (i = 0; i < xDim; ++i)                        \
  2563.     {                                    \
  2564.     vertexPtr = ((RectMeshPtr) curItem) -> vertices +        \
  2565.         RECTMESHVERTEX(((RectMeshPtr) curItem), i, 0);        \
  2566.     bgnline();                            \
  2567.     P(vertexPtr, 1);                        \
  2568.     for (j = 0; j < yDim; ++j)                    \
  2569.     {                                \
  2570.         V(vertexPtr);                        \
  2571.         vertexPtr += nY;                        \
  2572.     }                                \
  2573.     endline();                            \
  2574.     }                                    \
  2575.                                     \
  2576.     /*Draw the slow moving axes*/                    \
  2577.     for (j = 0; j < yDim; ++j)                        \
  2578.     {                                    \
  2579.     vertexPtr = ((RectMeshPtr) curItem) -> vertices +        \
  2580.             RECTMESHVERTEX(((RectMeshPtr) curItem), 0, j);    \
  2581.     bgnline();                            \
  2582.     P(vertexPtr, 1);                        \
  2583.     for (i = 0; i < xDim; ++i)                    \
  2584.     {                                \
  2585.         V(vertexPtr);                        \
  2586.         vertexPtr += nX;                        \
  2587.     }                                \
  2588.     endline();                            \
  2589.     }                                    \
  2590.     }
  2591.  
  2592. /*Wire frame monocolor rectangle traversal macro*/
  2593. #define TRAVERSEWMONOCOLORRECTMESH                        \
  2594.     {                                    \
  2595.     register int i, j;                            \
  2596.     int xDim, yDim;                            \
  2597.     register VertexPtr *vertexPtr;                    \
  2598.     int nX, nY;                                \
  2599.                                     \
  2600.     vertexPtr = ((RectMeshPtr) curItem) -> vertices;            \
  2601.     xDim = ((RectMeshPtr) curItem) -> xDim;                \
  2602.     yDim = ((RectMeshPtr) curItem) -> yDim;                \
  2603.     nX = (2 * yDim - 1);                        \
  2604.     nY = 2;                                \
  2605.                                     \
  2606.     /*Draw the fast moving axes*/                    \
  2607.     for (i = 0; i < xDim; ++i)                        \
  2608.     {                                    \
  2609.     vertexPtr = ((RectMeshPtr) curItem) -> vertices +        \
  2610.         RECTMESHVERTEX(((RectMeshPtr) curItem), i, 0);        \
  2611.     for (j = 0; j < yDim - 1; ++j)                    \
  2612.     {                                \
  2613.         bgnline();                            \
  2614.         P1(vertexPtr, 1);                        \
  2615.         V(vertexPtr);                        \
  2616.         vertexPtr += nY;                        \
  2617.         V(vertexPtr);                        \
  2618.         endline();                            \
  2619.     }                                \
  2620.     }                                    \
  2621.                                     \
  2622.     /*Draw the slow moving axes*/                    \
  2623.     for (j = 0; j < yDim; ++j)                        \
  2624.     {                                    \
  2625.     vertexPtr = ((RectMeshPtr) curItem) -> vertices +        \
  2626.             RECTMESHVERTEX(((RectMeshPtr) curItem), 0, j);    \
  2627.     for (i = 0; i < xDim - 1; ++i)                    \
  2628.     {                                \
  2629.         bgnline();                            \
  2630.         P2(vertexPtr, 1);                        \
  2631.         V(vertexPtr);                        \
  2632.         vertexPtr += nX;                        \
  2633.         V(vertexPtr);                        \
  2634.         endline();                            \
  2635.     }                                \
  2636.     }                                    \
  2637.     }
  2638.  
  2639.  
  2640. /*Rectangular mesh traversal macro*/
  2641. #define TRAVERSERECTMESH                        \
  2642.     {                                    \
  2643.     register int i, j;                        \
  2644.     int xDim, yDim;                            \
  2645.     register VertexPtr *vertexPtr;                    \
  2646.     int nX, nY;                            \
  2647.                                     \
  2648.     vertexPtr = ((RectMeshPtr) curItem) -> vertices;        \
  2649.     xDim = ((RectMeshPtr) curItem) -> xDim;                \
  2650.     yDim = ((RectMeshPtr) curItem) -> yDim;                \
  2651.     nY = 2;                                \
  2652.     nX = (yDim * 2 - 1);                        \
  2653.     for (i = 0; i < xDim - 1; ++i)                    \
  2654.     {                                \
  2655.         bgntmesh();                        \
  2656.         P(vertexPtr, 1);                    \
  2657.         V(vertexPtr);                    \
  2658.         vertexPtr += nX;                    \
  2659.         V(vertexPtr);                    \
  2660.         for (j = 1; j < yDim; ++j)                \
  2661.         {                            \
  2662.         vertexPtr += nY - nX;                \
  2663.         V(vertexPtr);                    \
  2664.         vertexPtr += nX;                \
  2665.         V(vertexPtr);                    \
  2666.         }                            \
  2667.         vertexPtr -= nX - 1;                \
  2668.         endtmesh();                        \
  2669.     }                                \
  2670.     }
  2671.  
  2672. /*Monocolor Rectangular mesh traversal macro*/
  2673. #define TRAVERSEMCRECTMESH                        \
  2674.     {                                    \
  2675.     register int i, j;                        \
  2676.     int xDim, yDim;                            \
  2677.     register VertexPtr *vertexPtr;                    \
  2678.     int nX, nY;                            \
  2679.                                     \
  2680.     vertexPtr = ((RectMeshPtr) curItem) -> vertices;        \
  2681.     xDim = ((RectMeshPtr) curItem) -> xDim;                \
  2682.     yDim = ((RectMeshPtr) curItem) -> yDim;                \
  2683.     nY = 2;                                \
  2684.     nX = (yDim * 2 - 1);                        \
  2685.     for (i = 0; i < xDim - 1; ++i)                    \
  2686.     {                                \
  2687.         for (j = 0; j < yDim - 1; ++j)                \
  2688.         {                                \
  2689.         bgntmesh();                        \
  2690.         P(vertexPtr + 1);                        \
  2691.         V(vertexPtr);                        \
  2692.         vertexPtr += nX;                    \
  2693.         V(vertexPtr);                        \
  2694.         vertexPtr += nY - nX;                    \
  2695.         V(vertexPtr);                        \
  2696.         vertexPtr += nX;                    \
  2697.         V(vertexPtr);                        \
  2698.         endtmesh();                        \
  2699.         vertexPtr -= nX;                    \
  2700.         }                                \
  2701.         vertexPtr += nY - 1;  /*-1 for missing center*/        \
  2702.     }                                \
  2703.     }
  2704. #endif
  2705.  
  2706. static void DrawCPolygon(curItem)
  2707. PicItemPtr curItem;
  2708. /*Draws a color map shaded polygon*/
  2709. {
  2710. #ifdef GRAPHICS
  2711. #define TRAVERSE TRAVERSEPLANARPOLY
  2712. #include "ScianStdCDraw.h"
  2713. #undef TRAVERSE
  2714. #endif
  2715. }
  2716.  
  2717. static void DrawWCPolygon(curItem)
  2718. PicItemPtr curItem;
  2719. {
  2720. #ifdef GRAPHICS
  2721. #define TRAVERSE TRAVERSECLOSEDPOLYLINE
  2722. #include "ScianStdCDraw.h"
  2723. #undef TRAVERSE
  2724. #endif
  2725. }
  2726.  
  2727. static void DrawCPolytri(curItem)
  2728. PicItemPtr curItem;
  2729. /*Draws a color map shaded polygon*/
  2730. {
  2731. #ifdef GRAPHICS
  2732. #define TRAVERSE TRAVERSEPOLYTRI
  2733. #include "ScianStdCDraw.h"
  2734. #undef TRAVERSE
  2735. #endif
  2736. }
  2737.  
  2738. static void DrawWCPolytri(curItem)
  2739. PicItemPtr curItem;
  2740. {
  2741. #ifdef GRAPHICS
  2742. #define TRAVERSE TRAVERSECLOSEDPOLYTRI
  2743. #include "ScianStdCDraw.h"
  2744. #undef TRAVERSE
  2745. #endif
  2746. }
  2747.  
  2748. static void DrawCPolyline(curItem)
  2749. PicItemPtr curItem;
  2750. /*Draws a color map shaded polyline*/
  2751. {
  2752. #ifdef GRAPHICS
  2753. #define TRAVERSE TRAVERSEPOLYLINE
  2754. #include "ScianStdCDraw.h"
  2755. #undef TRAVERSE
  2756. #endif
  2757. }
  2758.  
  2759. static void DrawCPolypoint(curItem)
  2760. PicItemPtr curItem;
  2761. /*Draws a color map shaded polyline*/
  2762. {
  2763. #ifdef GRAPHICS
  2764. #define TRAVERSE TRAVERSEPOLYPOINT
  2765. #include "ScianStdCDraw.h"
  2766. #undef TRAVERSE
  2767. #endif
  2768. }
  2769.  
  2770. static void DrawRGBPolygon(curItem)
  2771. PicItemPtr curItem;
  2772. {
  2773. #ifdef GRAPHICS
  2774. #define TRAVERSE TRAVERSEPLANARPOLY
  2775. #include "ScianStdRGBDraw.h"
  2776. #undef TRAVERSE
  2777. #endif
  2778. }
  2779.  
  2780. static void DrawRGBPolytri(curItem)
  2781. PicItemPtr curItem;
  2782. {
  2783. #ifdef GRAPHICS
  2784. #define TRAVERSE TRAVERSEPOLYTRI
  2785. #include "ScianStdRGBDraw.h"
  2786. #undef TRAVERSE
  2787. #endif
  2788. }
  2789.  
  2790. static void DrawWRGBPolygon(curItem)
  2791. PicItemPtr curItem;
  2792. {
  2793. #ifdef GRAPHICS
  2794. #define TRAVERSE TRAVERSECLOSEDPOLYLINE
  2795. #include "ScianStdRGBDraw.h"
  2796. #undef TRAVERSE
  2797. #endif
  2798. }
  2799.  
  2800. static void DrawWRGBPolytri(curItem)
  2801. PicItemPtr curItem;
  2802. {
  2803. #ifdef GRAPHICS
  2804. #define TRAVERSE TRAVERSECLOSEDPOLYTRI
  2805. #include "ScianStdRGBDraw.h"
  2806. #undef TRAVERSE
  2807. #endif
  2808. }
  2809.  
  2810. static void DrawRGBPolyline(curItem)
  2811. PicItemPtr curItem;
  2812. {
  2813. #ifdef GRAPHICS
  2814. #define TRAVERSE TRAVERSEPOLYLINE
  2815. #include "ScianStdRGBDraw.h"
  2816. #undef TRAVERSE
  2817. #endif
  2818. }
  2819.  
  2820. static void DrawRGBPolypoint(curItem)
  2821. PicItemPtr curItem;
  2822. {
  2823. #ifdef GRAPHICS
  2824. #define TRAVERSE TRAVERSEPOLYPOINT
  2825. #include "ScianStdRGBDraw.h"
  2826. #undef TRAVERSE
  2827. #endif
  2828. }
  2829. static void DrawCPPolygon(curItem)
  2830. PicItemPtr curItem;
  2831. /*Draws a color map shaded planarpolygon*/
  2832. {
  2833. #ifdef GRAPHICS
  2834. #define TRAVERSE TRAVERSEPLANARPOLY
  2835. #include "ScianStdCDraw.h"
  2836. #undef TRAVERSE
  2837. #endif
  2838. }
  2839.  
  2840. static void DrawRGBPPolygon(curItem)
  2841. PicItemPtr curItem;
  2842. /*Draws an RGB shaded planar polygon*/
  2843. {
  2844. #ifdef GRAPHICS
  2845. #define TRAVERSE TRAVERSEPLANARPOLY
  2846. #include "ScianStdRGBDraw.h"
  2847. #undef TRAVERSE
  2848. #endif
  2849. }
  2850.  
  2851.  
  2852. static void DrawWCRectMesh(curItem)
  2853. PicItemPtr curItem;
  2854. /*Draws a color map wire frame rect mesh*/
  2855. {
  2856. #ifdef GRAPHICS
  2857.     if (curLightShading == DEPTHCUELIGHT)
  2858.     {
  2859.         switch (curColorShading)
  2860.         {
  2861.             case NOCOLOR:
  2862. #define P PCDN
  2863. #define V VCDN
  2864.             TRAVERSEWRECTMESH;
  2865. #undef P
  2866. #undef V
  2867.             break;
  2868.             case MONOCOLOR:
  2869. #define P1 PCDM
  2870. #define P2 PCDMSKIP
  2871. #define V VCDM
  2872.             TRAVERSEWMONOCOLORRECTMESH;
  2873. #undef P1
  2874. #undef P2
  2875. #undef V
  2876.             break;
  2877.             case SMOOTHCOLOR:
  2878. #define P PCDS
  2879. #define V VCDS
  2880.             TRAVERSEWRECTMESH;
  2881. #undef P
  2882. #undef V
  2883.             break;
  2884.         }
  2885.     }
  2886.     else
  2887.     {
  2888.         switch (curColorShading)
  2889.         {
  2890.             case NOCOLOR:
  2891. #define P PCNN
  2892. #define V VCNN
  2893.             TRAVERSEWRECTMESH;
  2894. #undef P
  2895. #undef V
  2896.             break;
  2897.             case MONOCOLOR:
  2898. #define P1 PCNM
  2899. #define P2 PCNMSKIP
  2900. #define V VCNM
  2901.             TRAVERSEWMONOCOLORRECTMESH;
  2902. #undef P1
  2903. #undef P2
  2904. #undef V
  2905.             break;
  2906.             case SMOOTHCOLOR:
  2907. #define P PCNS
  2908. #define V VCNS
  2909.             TRAVERSEWRECTMESH;
  2910. #undef P
  2911. #undef V
  2912.             break;
  2913.         }
  2914.     }
  2915. #endif
  2916. }
  2917.  
  2918. static void DrawWRGBRectMesh(curItem)
  2919. PicItemPtr curItem;
  2920. /*Draws an RGB wire frame rectangular mesh*/
  2921. {
  2922. #ifdef GRAPHICS
  2923.     if (curLightShading == DEPTHCUELIGHT)
  2924.     {
  2925.         switch (curColorShading)
  2926.         {
  2927.             case NOCOLOR:
  2928. #define P PRDN
  2929. #define V VRDN
  2930.             TRAVERSEWRECTMESH;
  2931. #undef P
  2932. #undef V
  2933.             break;
  2934.             case MONOCOLOR:
  2935. #define P1 PRDM
  2936. #define P2 PRDMSKIP
  2937. #define V VRDM
  2938.             TRAVERSEWMONOCOLORRECTMESH;
  2939. #undef P1
  2940. #undef P2
  2941. #undef V
  2942.             break;
  2943.             case SMOOTHCOLOR:
  2944. #define P PRDS
  2945. #define V VRDS
  2946.             TRAVERSEWRECTMESH;
  2947. #undef P
  2948. #undef V
  2949.             break;
  2950.         }
  2951.     }
  2952.     else
  2953.     {
  2954.         switch (curColorShading)
  2955.         {
  2956.             case NOCOLOR:
  2957. #define P PRNN
  2958. #define V VRNN
  2959.             TRAVERSEWRECTMESH;
  2960. #undef P
  2961. #undef V
  2962.             break;
  2963.             case MONOCOLOR:
  2964. #define P1 PRNM
  2965. #define P2 PRNMSKIP
  2966. #define V VRNM
  2967.             TRAVERSEWMONOCOLORRECTMESH;
  2968. #undef P1
  2969. #undef P2
  2970. #undef V
  2971.             break;
  2972.             case SMOOTHCOLOR:
  2973. #define P PRNS
  2974. #define V VRNS
  2975.             TRAVERSEWRECTMESH;
  2976. #undef P
  2977. #undef V
  2978.             break;
  2979.         }
  2980.     }
  2981. #endif
  2982. }
  2983.  
  2984. static void DrawCRectMesh(curItem)
  2985. PicItemPtr curItem;
  2986. /*Draws a rectangular mesh in color map mode*/
  2987. {
  2988. #ifdef GRAPHICS
  2989.     switch (curLightShading)
  2990.     {
  2991.         case NOLIGHT:
  2992.         switch (curColorShading)
  2993.         {
  2994.             case NOCOLOR:
  2995. #define P PCNN
  2996. #define V VCNN
  2997.             TRAVERSERECTMESH;
  2998. #undef P
  2999. #undef V
  3000.             break;
  3001.             case MONOCOLOR:
  3002. #define P MCRPCNM
  3003. #define V VCNM
  3004.             TRAVERSEMCRECTMESH;
  3005. #undef P
  3006. #undef V
  3007.             break;
  3008.             case SMOOTHCOLOR:
  3009. #define P PCNS
  3010. #define V VCNS
  3011.             TRAVERSERECTMESH;
  3012. #undef P
  3013. #undef V
  3014.             break;
  3015.         }
  3016.         break;
  3017.         case MONOLIGHT:
  3018.         switch (curColorShading)
  3019.         {
  3020.             case NOCOLOR:
  3021. #define P PCMN
  3022. #define V VCMN
  3023.             TRAVERSERECTMESH;
  3024. #undef P
  3025. #undef V
  3026.             break;
  3027.             case MONOCOLOR:
  3028. #define P MCRPCNM
  3029. #define V VCMM
  3030.             TRAVERSEMCRECTMESH;
  3031. #undef P
  3032. #undef V
  3033.             break;
  3034.             case SMOOTHCOLOR:
  3035. #define P PCMS
  3036. #define V VCMS
  3037.             TRAVERSERECTMESH;
  3038. #undef P
  3039. #undef V
  3040.             break;
  3041.         }
  3042.         break;
  3043.         case SMOOTHLIGHT:
  3044.         switch (curColorShading)
  3045.         {
  3046.             case NOCOLOR:
  3047. #define P PCSN
  3048. #define V VCSN
  3049.             TRAVERSERECTMESH;
  3050. #undef P
  3051. #undef V
  3052.             break;
  3053.             case MONOCOLOR:
  3054. #define P MCRPCNM
  3055. #define V VCSM
  3056.             TRAVERSEMCRECTMESH;
  3057. #undef P
  3058. #undef V
  3059.             break;
  3060.             case SMOOTHCOLOR:
  3061. #define P PCSS
  3062. #define V VCSS
  3063.             TRAVERSERECTMESH;
  3064. #undef P
  3065. #undef V
  3066.             break;
  3067.         }
  3068.         break;
  3069.     }
  3070. #endif
  3071. }
  3072.  
  3073. int yaga = 0;
  3074.  
  3075. static void DrawRGBRectMesh(curItem)
  3076. PicItemPtr curItem;
  3077. /*Draws a rectangular mesh in RGB mode*/
  3078. {
  3079. #ifdef GRAPHICS
  3080.     switch (curLightShading)
  3081.     {
  3082.         case NOLIGHT:
  3083.         switch (curColorShading)
  3084.         {
  3085.             case NOCOLOR:
  3086. #define P PRNN
  3087. #define V VRNN
  3088.             TRAVERSERECTMESH;
  3089. #undef P
  3090. #undef V
  3091.             break;
  3092.             case MONOCOLOR:
  3093. #define P MCRPRNM
  3094. #define V VRNM
  3095.             TRAVERSEMCRECTMESH;
  3096. #undef P
  3097. #undef V
  3098.             break;
  3099.             case SMOOTHCOLOR:
  3100. #define P PRNS
  3101. #define V VRNS
  3102.             TRAVERSERECTMESH;
  3103. #undef P
  3104. #undef V
  3105.             break;
  3106.         }
  3107.         break;
  3108.         case MONOLIGHT:
  3109.         switch (curColorShading)
  3110.         {
  3111.             case NOCOLOR:
  3112. #define P PRMN
  3113. #define V VRMN
  3114.             TRAVERSERECTMESH;
  3115. #undef P
  3116. #undef V
  3117.             break;
  3118.             case MONOCOLOR:
  3119. #define P MCRPRNM
  3120. #define V VRMM
  3121.             TRAVERSEMCRECTMESH;
  3122. #undef P
  3123. #undef V
  3124.             break;
  3125.             case SMOOTHCOLOR:
  3126. #define P PRMS
  3127. #define V VRMS
  3128.             TRAVERSERECTMESH;
  3129. #undef P
  3130. #undef V
  3131.             break;
  3132.         }
  3133.         break;
  3134.         case SMOOTHLIGHT:
  3135.         switch (curColorShading)
  3136.         {
  3137.             case NOCOLOR:
  3138. #define P PRSN
  3139. #define V VRSN
  3140.             TRAVERSERECTMESH;
  3141. #undef P
  3142. #undef V
  3143.             break;
  3144.             case MONOCOLOR:
  3145. #define P MCRPRNM
  3146. #define V VRSM
  3147.             TRAVERSEMCRECTMESH;
  3148. #undef P
  3149. #undef V
  3150.             break;
  3151.             case SMOOTHCOLOR:
  3152. #define P PRSS
  3153. #define V VRSS
  3154.             TRAVERSERECTMESH;
  3155. #undef P
  3156. #undef V
  3157.             break;
  3158.         }
  3159.         break;
  3160.     }
  3161. #endif
  3162. }
  3163.  
  3164. void DrawCSphere(curItem)
  3165. PicItemPtr curItem;
  3166. /*Draws a sphere in cmap mode*/
  3167. {
  3168. #ifdef GRAPHICS
  3169.             {
  3170.                 Sphere curSphere;
  3171.                 float vx[3], vy[3], vz[3]; /*Vertices stuck out on those axes*/
  3172.                 
  3173.                 curSphere = *((SpherePtr) curItem);
  3174.     
  3175.                     if (!curIsTransparent)
  3176.                     {
  3177.                        backface(TRUE);
  3178.                     }
  3179.                 /*Draw the eight quadrants of the sphere*/
  3180.                 /* +x +y +z */
  3181.                 vx[0] = 1.0;
  3182.                 vx[1] = 0.0;
  3183.                 vx[2] = 0.0;
  3184.                 vy[0] = 0.0;
  3185.                 vy[1] = 1.0;
  3186.                 vy[2] = 0.0;
  3187.                 vz[0] = 0.0;
  3188.                 vz[1] = 0.0;
  3189.                 vz[2] = 1.0;
  3190.     
  3191.                 curRadius = curSphere. radius;
  3192.                 curCenter[0] = curSphere . centerVertex -> position[0];
  3193.                 curCenter[1] = curSphere . centerVertex -> position[1];
  3194.                 curCenter[2] = curSphere . centerVertex -> position[2];
  3195.                 DrawQuadrant(vx, vy, vz, 0);
  3196.     
  3197.                 /* +y -x +z*/
  3198.                 vx[0] = -1.0;
  3199.                 DrawQuadrant(vy, vx, vz, 0);
  3200.     
  3201.                 /* -x -y -z*/
  3202.                 vy[1] = -1.0;
  3203.                 DrawQuadrant(vx, vy, vz, 0);
  3204.     
  3205.                 /* -y +x +z*/
  3206.                 vx[0] = 1.0;
  3207.                 DrawQuadrant(vy, vx, vz, 0);
  3208.     
  3209.                 /* +x -y -z*/
  3210.                 vz[2] = -1.0;
  3211.                 DrawQuadrant(vx, vy, vz, 0);
  3212.     
  3213.                 /* +y +x -z*/
  3214.                 vy[1] = 1.0;
  3215.                 DrawQuadrant(vy, vx, vz, 0);
  3216.     
  3217.                 /* -x +y -z*/
  3218.                 vx[0] = -1.0;
  3219.                 DrawQuadrant(vx, vy, vz, 0);
  3220.     
  3221.                 /* -y, -x, -z*/
  3222.                 vy[1] = -1.0;
  3223.                 DrawQuadrant(vy, vx, vz, 0);
  3224.     
  3225.                     if (!curIsTransparent)
  3226.                     {
  3227.                        backface(FALSE);
  3228.                     }
  3229.             }
  3230. #endif
  3231. }
  3232.  
  3233. void DrawSFrustum(curItem)
  3234. PicItemPtr curItem;
  3235. /*Draws a skeletal frustum*/
  3236. {
  3237. #ifdef GRAPHICS
  3238.     bgnline();
  3239.     v3f(((FrustumPtr) curItem) -> end1);
  3240.     v3f(((FrustumPtr) curItem) -> end2);
  3241.     endline();
  3242. #endif
  3243. }
  3244.  
  3245. void DrawCFrustum(curItem)
  3246. PicItemPtr curItem;
  3247. /*Draws a color map frustum*/
  3248. {
  3249. #ifdef GRAPHICS
  3250.     Frustum curFrustum;
  3251.     float a[3];        /*Axial unit vector*/
  3252.     float r[CYLSIDES][3];
  3253.     double length;    /*Length of cylinder*/
  3254.     double nf;        /*Normalization factor*/
  3255.             /*Radial units around cylinder*/
  3256.     int end;        /*Counter for which end*/
  3257.     int b;        /*Counter around radius*/
  3258.     int d;        /*Delta for subdivision*/
  3259.     int k;        /*Random counter*/
  3260.  
  3261.     if (!curIsTransparent)
  3262.     {
  3263.     backface(TRUE);
  3264.     }
  3265.  
  3266.     /*Copy the frustum into curFrustum for speed*/
  3267.     curFrustum = *((FrustumPtr) curItem);
  3268.  
  3269.     /*First make an axial unit vector*/
  3270.     a[0] = curFrustum . end2[0] -
  3271.        curFrustum . end1[0];
  3272.     a[1] = curFrustum . end2[1] -
  3273.        curFrustum . end1[1];
  3274.     a[2] = curFrustum . end2[2] -
  3275.        curFrustum . end1[2];
  3276.     length = sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]);
  3277.     nf = 1.0 / length;
  3278.     a[0] *= nf; a[1] *= nf; a[2] *= nf;
  3279.  
  3280.     /*See if it's nearly colinear with i*/
  3281.     if (ABS(a[0]) > 0.8)
  3282.     {
  3283.     /*It is, so cross by j to get first r*/
  3284.     r[0][0] = -a[2];
  3285.     r[0][1] = 0.0;
  3286.     r[0][2] = a[0];
  3287.     }
  3288.     else
  3289.     {
  3290.     /*It isn't, so cross by i to get first r*/
  3291.     r[0][0] = 0.0;
  3292.     r[0][1] = a[2];
  3293.     r[0][2] = -a[1];
  3294.     }
  3295.     
  3296.     /*Normalize r*/
  3297.     length = sqrt(r[0][0]*r[0][0] + r[0][1]*r[0][1] + r[0][2]*r[0][2]);
  3298.     nf = 1.0 / length;
  3299.     r[0][0] *= nf; r[0][1] *= nf, r[0][2] *= nf;
  3300.  
  3301.     /*Cross a with first radial unit to get orthogonal unit*/
  3302.     CROSS(a, r[0], r[CYLSIDES / 4]);
  3303.  
  3304.     /*Fill out point radii 3 and 4 by reversing 1 and 2*/
  3305.     r[CYLSIDES / 2][0] = -r[0][0];
  3306.     r[CYLSIDES / 2][1] = -r[0][1];
  3307.     r[CYLSIDES / 2][2] = -r[0][2];
  3308.  
  3309.     r[CYLSIDES / 4 * 3][0] = -r[CYLSIDES / 4][0];
  3310.     r[CYLSIDES / 4 * 3][1] = -r[CYLSIDES / 4][1];
  3311.     r[CYLSIDES / 4 * 3][2] = -r[CYLSIDES / 4][2];
  3312.  
  3313.     /*Subdivide the sides of the cylinder*/
  3314.     k = 0;
  3315.     for (d = CYLSIDES / 4; d > 1; d /= 2)
  3316.     {
  3317.     register double cef_2;    /*Chord extension factor/2*/
  3318.     
  3319.     cef_2 = cefs_2[k];
  3320.     ++k;
  3321.     
  3322.     for (b = 0; b < CYLSIDES; b += d)
  3323.     {
  3324.         register int m, e;    /*Midpoint and endpoint*/
  3325.  
  3326.         /*Interpolate center of chord*/
  3327.         e = (b + d) & (CYLSIDES - 1);    /*Clip circular*/
  3328.         m = b + d / 2;
  3329.         r[m][0] = (r[b][0] + r[e][0]) * cef_2;
  3330.         r[m][1] = (r[b][1] + r[e][1]) * cef_2;
  3331.         r[m][2] = (r[b][2] + r[e][2]) * cef_2;
  3332.     }
  3333.     }
  3334.  
  3335.     /*Draw the cylinder*/
  3336.     
  3337. #ifndef PSYCHEDELIC
  3338.     if (rgbp == false)
  3339.     {
  3340.     float v[3];
  3341.     
  3342.     bgntmesh();
  3343.     SetRealColor(r[CYLSIDES - 1][0]);
  3344.     v[0] = curFrustum . rad2 * r[CYLSIDES - 1][0] + 
  3345.            curFrustum . end2[0];
  3346.     v[1] = curFrustum . rad2 * r[CYLSIDES - 1][1] + 
  3347.            curFrustum . end2[1];
  3348.     v[2] = curFrustum . rad2 * r[CYLSIDES - 1][2] + 
  3349.            curFrustum . end2[2];
  3350.     v3f(v);
  3351.     v[0] = curFrustum . rad1 * r[CYLSIDES - 1][0] + 
  3352.            curFrustum . end1[0];
  3353.     v[1] = curFrustum . rad1 * r[CYLSIDES - 1][1] + 
  3354.            curFrustum . end1[1];
  3355.     v[2] = curFrustum . rad1 * r[CYLSIDES - 1][2] + 
  3356.            curFrustum . end1[2];
  3357.     v3f(v);
  3358.  
  3359.     for (k = 0; k < CYLSIDES; ++k)
  3360.     {
  3361.         SetRealColor(r[k][0]);
  3362.         v[0] = curFrustum . rad2 * r[k][0] + 
  3363.            curFrustum . end2[0];
  3364.         v[1] = curFrustum . rad2 * r[k][1] + 
  3365.            curFrustum . end2[1];
  3366.         v[2] = curFrustum . rad2 * r[k][2] + 
  3367.            curFrustum . end2[2];
  3368.         v3f(v);
  3369.         v[0] = curFrustum . rad1 * r[k][0] + 
  3370.            curFrustum . end1[0];
  3371.         v[1] = curFrustum . rad1 * r[k][1] + 
  3372.            curFrustum . end1[1];
  3373.         v[2] = curFrustum . rad1 * r[k][2] + 
  3374.            curFrustum . end1[2];
  3375.         v3f(v);
  3376.     }
  3377.     endtmesh();
  3378.  
  3379.     /*Do top cap*/
  3380.     SetRealColor(a[0]);
  3381.     bgnpolygon();
  3382.     for (k = 0; k < CYLSIDES; ++k)
  3383.     {
  3384.         v[0] = curFrustum . rad2 * r[k][0] + 
  3385.            curFrustum . end2[0];
  3386.         v[1] = curFrustum . rad2 * r[k][1] + 
  3387.            curFrustum . end2[1];
  3388.         v[2] = curFrustum . rad2 * r[k][2] + 
  3389.            curFrustum . end2[2];
  3390.         v3f(v);
  3391.     }
  3392.     endpolygon();
  3393.  
  3394.     /*Do bottom cap*/
  3395.     SetRealColor(-a[0]);
  3396.     bgnpolygon();
  3397.     for (k = CYLSIDES - 1; k >= 0; --k)
  3398.     {
  3399.         v[0] = curFrustum . rad1 * r[k][0] + 
  3400.            curFrustum . end1[0];
  3401.         v[1] = curFrustum . rad1 * r[k][1] + 
  3402.            curFrustum . end1[1];
  3403.         v[2] = curFrustum . rad1 * r[k][2] + 
  3404.            curFrustum . end1[2];
  3405.         v3f(v);
  3406.     }
  3407.     endpolygon();
  3408.     }
  3409.     else
  3410. #endif
  3411.     {
  3412.     float v[3];
  3413.  
  3414.     bgntmesh();
  3415.     N3F(r[CYLSIDES - 1]);
  3416.     v[0] = curFrustum . rad2 * r[CYLSIDES - 1][0] + 
  3417.            curFrustum . end2[0];
  3418.     v[1] = curFrustum . rad2 * r[CYLSIDES - 1][1] + 
  3419.            curFrustum . end2[1];
  3420.     v[2] = curFrustum . rad2 * r[CYLSIDES - 1][2] + 
  3421.            curFrustum . end2[2];
  3422.     v3f(v);
  3423.     v[0] = curFrustum . rad1 * r[CYLSIDES - 1][0] + 
  3424.            curFrustum . end1[0];
  3425.     v[1] = curFrustum . rad1 * r[CYLSIDES - 1][1] + 
  3426.            curFrustum . end1[1];
  3427.     v[2] = curFrustum . rad1 * r[CYLSIDES - 1][2] + 
  3428.            curFrustum . end1[2];
  3429.     v3f(v);
  3430.  
  3431.     for (k = 0; k < CYLSIDES; ++k)
  3432.     {
  3433.         N3F(r[k]);
  3434.         v[0] = curFrustum . rad2 * r[k][0] + 
  3435.            curFrustum . end2[0];
  3436.         v[1] = curFrustum . rad2 * r[k][1] + 
  3437.            curFrustum . end2[1];
  3438.         v[2] = curFrustum . rad2 * r[k][2] + 
  3439.            curFrustum . end2[2];
  3440.         v3f(v);
  3441.         v[0] = curFrustum . rad1 * r[k][0] + 
  3442.            curFrustum . end1[0];
  3443.         v[1] = curFrustum . rad1 * r[k][1] + 
  3444.            curFrustum . end1[1];
  3445.         v[2] = curFrustum . rad1 * r[k][2] + 
  3446.            curFrustum . end1[2];
  3447.         v3f(v);
  3448.     }
  3449.     endtmesh();
  3450.  
  3451.     /*Do top cap*/
  3452.     N3F(a);
  3453.     bgnpolygon();
  3454.     for (k = 0; k < CYLSIDES; ++k)
  3455.     {
  3456.         v[0] = curFrustum . rad2 * r[k][0] + 
  3457.            curFrustum . end2[0];
  3458.         v[1] = curFrustum . rad2 * r[k][1] + 
  3459.            curFrustum . end2[1];
  3460.         v[2] = curFrustum . rad2 * r[k][2] + 
  3461.            curFrustum . end2[2];
  3462.         v3f(v);
  3463.     }
  3464.     endpolygon();
  3465.  
  3466.     /*Do bottom cap*/
  3467.     a[0] = -a[0];
  3468.     a[1] = -a[1];
  3469.     a[2] = -a[2];
  3470.     N3F(a);
  3471.     bgnpolygon();
  3472.     for (k = CYLSIDES - 1; k >= 0; --k)
  3473.     {
  3474.         v[0] = curFrustum . rad1 * r[k][0] + 
  3475.            curFrustum . end1[0];
  3476.         v[1] = curFrustum . rad1 * r[k][1] + 
  3477.            curFrustum . end1[1];
  3478.         v[2] = curFrustum . rad1 * r[k][2] + 
  3479.            curFrustum . end1[2];
  3480.         v3f(v);
  3481.     }
  3482.     endpolygon();
  3483.     }
  3484.     if (!curIsTransparent)
  3485.     {
  3486.     backface(FALSE);
  3487.     }
  3488. #endif
  3489. }
  3490.  
  3491. void DrawCPolygons(item)
  3492. PicItemPtr item;
  3493. /*Draws a bunch of polygons in cmode*/
  3494. {
  3495. #ifdef GRAPHICS
  3496.     PolyPtr curItem;
  3497.  
  3498.     curItem = ((PolysPtr) item) -> polygons;
  3499.     while (curItem)
  3500.     {
  3501.     DrawCPolygon(curItem);
  3502.     curItem = (PolyPtr) curItem -> item . next;
  3503.     }
  3504. #endif
  3505. }
  3506.  
  3507. void DrawRGBPolygons(item)
  3508. PicItemPtr item;
  3509. /*Draws a bunch of polygons in RGB mode*/
  3510. {
  3511. #ifdef GRAPHICS
  3512.     PolyPtr curItem;
  3513.  
  3514.     if (!curIsTransparent && ((PolysPtr) item) -> enclosed && !orderReversed)    
  3515.     {
  3516.     backface(TRUE);
  3517.     }
  3518.     curItem = ((PolysPtr) item) -> polygons;
  3519.     while (curItem)
  3520.     {
  3521.     DrawRGBPolygon(curItem);
  3522.     curItem = (PolyPtr) curItem -> item . next;
  3523.     }
  3524.     if (!curIsTransparent && ((PolysPtr) item) -> enclosed && !orderReversed)    
  3525.     {
  3526.     backface(FALSE);
  3527.     }
  3528. #endif
  3529. }
  3530.  
  3531. void DrawWCPolygons(item)
  3532. PicItemPtr item;
  3533. /*Draws a bunch of polygons as wire frames*/
  3534. {
  3535. #ifdef GRAPHICS
  3536.     PolyPtr curItem;
  3537.     curItem = ((PolysPtr) item) -> polygons;
  3538.     while (curItem)
  3539.     {
  3540.     DrawWCPolygon(curItem);
  3541.     curItem = (PolyPtr) curItem -> item . next;
  3542.     }
  3543. #endif
  3544. }
  3545.  
  3546. void DrawWRGBPolygons(item)
  3547. PicItemPtr item;
  3548. /*Draws a bunch of polygons as wire frames*/
  3549. {
  3550. #ifdef GRAPHICS
  3551.     PolyPtr curItem;
  3552.     curItem = ((PolysPtr) item) -> polygons;
  3553.     while (curItem)
  3554.     {
  3555.     DrawWRGBPolygon(curItem);
  3556.     curItem = (PolyPtr) curItem -> item . next;
  3557.     }
  3558. #endif
  3559. }
  3560.  
  3561. #ifdef GRAPHICS
  3562. typedef void (* DrawFunc)();
  3563.  
  3564. /*Drawing Table*/
  3565.  
  3566. DrawFunc drawFuncs[NPICITEMTYPES][DQ_FULL + 1][2] =
  3567.     {
  3568.     /*    Wireframe C     Wireframe RGB       Full C          Full RGB           */
  3569.     {{DrawWCPolygon,  DrawWRGBPolygon }, {DrawCPolygon,   DrawRGBPolygon }},
  3570.     {{DrawSFrustum,   DrawSFrustum    }, {DrawCFrustum,   DrawCFrustum   }},
  3571.     {{DrawCSphere,    DrawCSphere     }, {DrawCSphere,    DrawCSphere    }},
  3572.     {{DrawWCRectMesh, DrawWRGBRectMesh}, {DrawCRectMesh,  DrawRGBRectMesh}},
  3573.     {{DrawCPPolygon,  DrawRGBPPolygon }, {DrawCPPolygon,  DrawRGBPPolygon}},
  3574.     {{DrawWCPolygons, DrawWRGBPolygons}, {DrawCPolygons,  DrawRGBPolygons}},
  3575.     {{DrawCPolyline,  DrawRGBPolyline }, {DrawCPolyline,  DrawRGBPolyline}},
  3576.     {{DrawCPolypoint, DrawRGBPolypoint}, {DrawCPolypoint, DrawRGBPolypoint}},
  3577.     {{DrawWCPolytri,  DrawWRGBPolytri }, {DrawCPolytri,   DrawRGBPolytri }}
  3578.     };
  3579.  
  3580. #endif
  3581.  
  3582. #ifdef PROTO
  3583. void PrepareToDraw(Bool isTransparent, int lightShading, int colorShading, ObjPtr colors)
  3584. #else
  3585. void PrepareToDraw(isTransparent, lightShading, colorShading, colors)
  3586. Bool isTransparent;
  3587. int lightShading;
  3588. int colorShading;
  3589. ObjPtr colors;
  3590. #endif
  3591. /*Prepares to do some drawing*/
  3592. {
  3593.     /*Store light and color shading*/
  3594.     curLightShading = lightShading;
  3595.     curColorShading = colorShading;
  3596.  
  3597.     if ((drawingQuality != DQ_FULL && curLightShading != DEPTHCUELIGHT)
  3598.     || overrideColor)
  3599.     {
  3600.     curLightShading = NOLIGHT;
  3601.     }
  3602.  
  3603.     /*And the transparency*/
  3604.     curIsTransparent = isTransparent;
  3605.     SetPalette(colors);
  3606.  
  3607.     /*Set the color mode*/
  3608.     if (rgbp == false)
  3609.     {
  3610.     curColorMode = CMODECMAP;
  3611.     }
  3612.     else
  3613.     {
  3614.     curColorMode = CMODERGB;
  3615.     }
  3616.  
  3617. #ifdef GRAPHICS
  3618.     /*Set shading model*/
  3619.     shademodel(shadeModels[curColorMode][curLightShading][curColorShading]);
  3620.  
  3621.     if ((curLightShading == DEPTHCUELIGHT) && hasDepthCue)
  3622.     {
  3623.     /*Set depth cueing*/
  3624.     depthcue(TRUE);
  3625.     }
  3626.     else if (overrideColor == false)
  3627. #endif
  3628.     {
  3629.     /*Set the default color for skeleton*/
  3630.     if (curSpace)
  3631.     {
  3632.         ObjPtr panel, color, var;
  3633.         real rgb[3];
  3634.     
  3635.         panel = GetVar(curSpace, BACKPANEL);
  3636.         if (panel)
  3637.         {
  3638.         var = GetVar(panel, BACKGROUND);
  3639.         if (var && IsRealArray(var) && RANK(var) == 1 && DIMS(var)[0] == 3)
  3640.         {
  3641.             Array2CArray(rgb, var);
  3642.         }
  3643.         else if (var && IsInt(var))
  3644.         {
  3645.             rgb[0] = uiColors[GetInt(var)][0] / 255.0;
  3646.             rgb[1] = uiColors[GetInt(var)][1] / 255.0;
  3647.             rgb[2] = uiColors[GetInt(var)][2] / 255.0;
  3648.         }
  3649.         else
  3650.         {
  3651.             rgb[0] = rgb[1] = rgb[2] = 0.0;
  3652.         }
  3653.         }
  3654.         if (rgb[0] + rgb[1] + rgb[2] > 1.5)
  3655.         {
  3656.         SetUIColor(UIBLACK);
  3657.         }
  3658.         else
  3659.         {
  3660.         SetUIColor(UIWHITE);
  3661.         }
  3662.     }
  3663.     }
  3664. }
  3665.  
  3666. void DoneDrawing()
  3667. /*Done drawing a picture*/
  3668. {
  3669. #ifdef GRAPHICS
  3670.     if (hasDepthCue)
  3671.     {
  3672.     depthcue(FALSE);
  3673.     }
  3674. #endif
  3675. }
  3676.  
  3677. void ZeroPictureTime()
  3678. /*Zeroes the picture time*/
  3679. {
  3680.     pictureTime = 0;
  3681. }
  3682.  
  3683. long GetPictureTime()
  3684. /*Gets the picture time*/
  3685. {
  3686.     return pictureTime;
  3687. }
  3688.  
  3689. #ifdef PROTO
  3690. void DrawPicture(ObjPtr pic, Bool isTransparent, int lightShading, int colorShading, ObjPtr colors)
  3691. #else
  3692. void DrawPicture(pic, isTransparent, lightShading, colorShading, colors)
  3693. ObjPtr pic;
  3694. Bool isTransparent;
  3695. int lightShading;
  3696. int colorShading;
  3697. ObjPtr colors;
  3698. #endif
  3699. /*Draws picture pic.  isTransparent if transparent*/
  3700. {
  3701. #ifdef GRAPHICS
  3702.     PicItemPtr curItem;
  3703.     ObjPtr repObj;
  3704.     DrawFunc drawFunc;
  3705.     int qualIndex;
  3706.     long beginTime;
  3707.     struct tms buffer;
  3708.  
  3709.     beginTime = times(&buffer);
  3710.  
  3711.     /*Calculate the quality index*/
  3712.     qualIndex = drawingQuality;
  3713.  
  3714.     /*Make the picture deformed*/
  3715.     MakeVar(pic, PICDEFORMED);
  3716.  
  3717.     /*Prepare to draw*/
  3718.     PrepareToDraw(isTransparent, lightShading, colorShading, colors);
  3719.  
  3720.     switch (curColorMode)
  3721.     {
  3722.     case CMODECMAP:
  3723.         if (lightShading == DEPTHCUELIGHT)
  3724.         {
  3725.             PrepareToDrawCDepthCue;
  3726.         }
  3727.         else
  3728.         {
  3729.             PrepareToDrawC;
  3730.         }
  3731.         break;
  3732.     case CMODERGB:
  3733.         if (lightShading == DEPTHCUELIGHT)
  3734.         {
  3735.             PrepareToDrawRGBDepthCue;
  3736.         }
  3737.         else
  3738.         {
  3739.             PrepareToDrawRGB;
  3740.         }
  3741.         break;
  3742.     }
  3743.     if (qualIndex == DQ_DOTS)
  3744.     {
  3745.     switch (curColorMode)
  3746.     {
  3747.         case CMODECMAP:
  3748. #define TRAVERSE TRAVERSEDOTS
  3749. #include "ScianStdCDraw.h"
  3750. #undef TRAVERSE
  3751.         break;
  3752.         case CMODERGB:
  3753. #define TRAVERSE TRAVERSEDOTS
  3754. #include "ScianStdRGBDraw.h"
  3755. #undef TRAVERSE
  3756.         break;
  3757.     }
  3758.     }
  3759.     else
  3760.     {
  3761.     curItem = ((PicPtr) pic) -> items;
  3762.     
  3763.     switch (curColorMode)
  3764.     {
  3765.         case CMODECMAP:
  3766.         while (curItem)
  3767.         {
  3768.             int proximity;
  3769.             int k;
  3770.             if (curItem -> type < 0 || curItem -> type >= NPICITEMTYPES)
  3771.             {
  3772.             char errStr[256];
  3773.             sprintf(errStr, "Item type %d not valid", curItem -> type);
  3774.             ReportError("DrawPicture", errStr);
  3775.             continue;
  3776.             }
  3777.             proximity = curItem -> proximity;
  3778.             if (proximity > 5 || proximity < -5)
  3779.             {
  3780.             ReportError("DrawPicture", "Bad proximity");
  3781.             continue;
  3782.             }
  3783.             if (proximity > 0)
  3784.             {
  3785.             for (k = 0; k < proximity; ++k)
  3786.             {
  3787.                 NudgeCloser();
  3788.             }
  3789.             }
  3790.             else if (proximity < 0)
  3791.             {
  3792.             for (k = 0; k > proximity; --k)
  3793.             {
  3794.                 NudgeFarther();
  3795.             }
  3796.             }
  3797.             drawFunc = drawFuncs[curItem -> type][qualIndex][0];
  3798.             if (drawFunc)
  3799.             {
  3800.             (*drawFunc)(curItem);
  3801.             }
  3802.             if (proximity > 0)
  3803.             {
  3804.             for (k = 0; k < proximity; ++k)
  3805.             {
  3806.                 NudgeFarther();
  3807.             }
  3808.             }
  3809.             else if (proximity < 0)
  3810.             {
  3811.             for (k = 0; k > proximity; --k)
  3812.             {
  3813.                 NudgeCloser();
  3814.             }
  3815.             }
  3816.             curItem = curItem -> next;
  3817.         }
  3818.         break;
  3819.         case CMODERGB:
  3820.         if (overrideColor)
  3821.         {
  3822.             lmcolor(LMC_NULL);
  3823.         }
  3824.         else if (lightShading == NOLIGHT)
  3825.         {
  3826.             lmcolor(LMC_COLOR);
  3827.         }
  3828.         else
  3829.         {
  3830.             lmcolor(LMC_DIFFUSE);
  3831.         }
  3832.     
  3833.         while (curItem)
  3834.         {
  3835.             int proximity;
  3836.             int k;
  3837.             if (curItem -> type < 0 || curItem -> type >= NPICITEMTYPES)
  3838.             {
  3839.             char errStr[256];
  3840.             sprintf(errStr, "Item type %d not valid", curItem -> type);
  3841.             ReportError("DrawPicture", errStr);
  3842.             continue;
  3843.             }
  3844.             proximity = curItem -> proximity;
  3845.             if (proximity > 5 || proximity < -5)
  3846.             {
  3847.             ReportError("DrawPicture", "Bad proximity");
  3848.             continue;
  3849.             }
  3850.             if (proximity > 0)
  3851.             {
  3852.             for (k = 0; k < proximity; ++k)
  3853.             {
  3854.                 NudgeCloser();
  3855.             }
  3856.             }
  3857.             else if (proximity < 0)
  3858.             {
  3859.             for (k = 0; k > proximity; --k)
  3860.             {
  3861.                 NudgeFarther();
  3862.             }
  3863.             }
  3864.             drawFunc = drawFuncs[curItem -> type][qualIndex][1];
  3865.             (*drawFunc)(curItem);
  3866.             if (proximity > 0)
  3867.             {
  3868.             for (k = 0; k < proximity; ++k)
  3869.             {
  3870.                 NudgeFarther();
  3871.             }
  3872.             }
  3873.             else if (proximity < 0)
  3874.             {
  3875.             for (k = 0; k > proximity; --k)
  3876.             {
  3877.                 NudgeCloser();
  3878.             }
  3879.             }
  3880.             curItem = curItem -> next;
  3881.         }
  3882.         break;
  3883.     }
  3884.     }
  3885.  
  3886.     DoneDrawing();
  3887.  
  3888.     pictureTime += (times(&buffer) - beginTime);
  3889. #endif
  3890. }
  3891.  
  3892. static PolysPtr curPolys;
  3893. static ObjPtr curPicture;
  3894. static int curColorIndex;
  3895.  
  3896. void QuadrantPolys(r1, r2, r3, level)
  3897. float r1[3];
  3898. float r2[3];
  3899. float r3[3];
  3900. int level;
  3901. /*Emits a quadrant of sphere at center curCenter with radius curRadius given 
  3902.   radial normal vectors r1, r2, and r3, using current color table, at recursion 
  3903.   level level into curPolys*/
  3904. {
  3905.     if (level >= curSub)
  3906.     {
  3907.     /*Maximum number of subdivisions has been reached*/
  3908.     Vertex *v[3];
  3909.     v[0] = NewVertex(curPicture, VF_SAMEPLACE);
  3910.     v[1] = NewVertex(curPicture, VF_SAMEPLACE);
  3911.     v[2] = NewVertex(curPicture, VF_SAMEPLACE);
  3912.     v[0] -> position[0] = curCenter[0] + r1[0] * curRadius;
  3913.     v[0] -> position[1] = curCenter[1] + r1[1] * curRadius;
  3914.     v[0] -> position[2] = curCenter[2] + r1[2] * curRadius;
  3915.     v[1] -> position[0] = curCenter[0] + r2[0] * curRadius;
  3916.     v[1] -> position[1] = curCenter[1] + r2[1] * curRadius;
  3917.     v[1] -> position[2] = curCenter[2] + r2[2] * curRadius;
  3918.     v[2] -> position[0] = curCenter[0] + r3[0] * curRadius;
  3919.     v[2] -> position[1] = curCenter[1] + r3[1] * curRadius;
  3920.     v[2] -> position[2] = curCenter[2] + r3[2] * curRadius;
  3921.  
  3922.     v[0] -> normal[0] = r1[0];
  3923.     v[0] -> normal[1] = r1[1];
  3924.     v[0] -> normal[2] = r1[2];
  3925.     v[1] -> normal[0] = r2[0];
  3926.     v[1] -> normal[1] = r2[1];
  3927.     v[1] -> normal[2] = r2[2];
  3928.     v[2] -> normal[0] = r3[0];
  3929.     v[2] -> normal[1] = r3[1];
  3930.     v[2] -> normal[2] = r3[2];
  3931.  
  3932.     v[0] -> colorIndex = curColorIndex;
  3933.     v[1] -> colorIndex = curColorIndex;
  3934.     v[2] -> colorIndex = curColorIndex;
  3935.  
  3936.     AppendSPolyToPolys(curPolys, 3, v);
  3937.     }
  3938.     else
  3939.     {
  3940.     /*Do another subdivision*/
  3941.     float r12[3], r23[3], r31[3];    /*Inner triangle subdivisions*/
  3942.     r12[0] = (r1[0] + r2[0]);
  3943.     r12[1] = (r1[1] + r2[1]);
  3944.     r12[2] = (r1[2] + r2[2]);
  3945.     r23[0] = (r2[0] + r3[0]);
  3946.     r23[1] = (r2[1] + r3[1]);
  3947.     r23[2] = (r2[2] + r3[2]);
  3948.     r31[0] = (r3[0] + r1[0]);
  3949.     r31[1] = (r3[1] + r1[1]);
  3950.     r31[2] = (r3[2] + r1[2]);
  3951.     NORMALIZE(r12);
  3952.     NORMALIZE(r23);
  3953.     NORMALIZE(r31);
  3954.  
  3955.     /*Draw the subdivisions*/
  3956.     QuadrantPolys(r1, r12, r31, level + 1);
  3957.     QuadrantPolys(r12, r2, r23, level + 1);
  3958.     QuadrantPolys(r23, r3, r31, level + 1);
  3959.     QuadrantPolys(r12, r23, r31, level + 1);
  3960.     }
  3961. }
  3962.  
  3963. #ifdef PROTO
  3964. PolysPtr ConvertSphereOntoPicture(ObjPtr picture, VertexPtr center, real radius, int flags, int nSubdivisions)
  3965. #else
  3966. PolysPtr ConvertSphereOntoPicture(picture, center, radius, flags, nSubdivisions)
  3967. ObjPtr picture;
  3968. VertexPtr center;
  3969. real radius;
  3970. int flags;
  3971. int nSubdivisions;
  3972. #endif
  3973. /*Returns a polys object of sphere*/
  3974. {
  3975.     float vx[3], vy[3], vz[3]; /*Vertices stuck out on those axes*/
  3976.     VertexPtr center2;
  3977.  
  3978.     curSub = nSubdivisions;        
  3979.     curPolys = AppendPolysToPicture(picture);
  3980.     curPicture = picture;
  3981.     curPolys -> enclosed = true;
  3982.  
  3983.     /*Make the center point*/
  3984.  
  3985.     center2 = NewVertex(picture, flags);
  3986.     center2 -> colorIndex = center -> colorIndex;
  3987.     center2 -> position[0] = center -> position[0];
  3988.     center2 -> position[1] = center -> position[1];
  3989.     center2 -> position[2] = center -> position[2];
  3990.  
  3991.  
  3992.     /*Make the eight quadrants of the sphere*/
  3993.     /* +x +y +z */
  3994.     vx[0] = 1.0;
  3995.     vx[1] = 0.0;
  3996.     vx[2] = 0.0;
  3997.     vy[0] = 0.0;
  3998.     vy[1] = 1.0;
  3999.     vy[2] = 0.0;
  4000.     vz[0] = 0.0;
  4001.     vz[1] = 0.0;
  4002.     vz[2] = 1.0;
  4003.     
  4004.     curRadius = radius;
  4005.     curCenter[0] = center -> position[0];
  4006.     curCenter[1] = center -> position[1];
  4007.     curCenter[2] = center -> position[2];
  4008.     curColorIndex = center -> colorIndex;
  4009.     QuadrantPolys(vx, vy, vz, 0);
  4010.     
  4011.     /* +y -x +z*/
  4012.     vx[0] = -1.0;
  4013.     QuadrantPolys(vy, vx, vz, 0);
  4014.     
  4015.     /* -x -y -z*/
  4016.     vy[1] = -1.0;
  4017.     QuadrantPolys(vx, vy, vz, 0);
  4018.     
  4019.     /* -y +x +z*/
  4020.     vx[0] = 1.0;
  4021.     QuadrantPolys(vy, vx, vz, 0);
  4022.     
  4023.     /* +x -y -z*/
  4024.     vz[2] = -1.0;
  4025.     QuadrantPolys(vx, vy, vz, 0);
  4026.     
  4027.     /* +y +x -z*/
  4028.     vy[1] = 1.0;
  4029.     QuadrantPolys(vy, vx, vz, 0);
  4030.     
  4031.     /* -x +y -z*/
  4032.     vx[0] = -1.0;
  4033.     QuadrantPolys(vx, vy, vz, 0);
  4034.     
  4035.     /* -y, -x, -z*/
  4036.     vy[1] = -1.0;
  4037.     QuadrantPolys(vy, vx, vz, 0);
  4038.  
  4039.     return curPolys;
  4040. }
  4041.  
  4042. #ifdef PROTO
  4043. void ConvertFrustumOntoPicture(ObjPtr picture, float end1[3], float rad1,
  4044.         float end2[3], float rad2, int nSubdivisions, Bool capEnds)
  4045. #else
  4046. void ConvertFrustumOntoPicture(picture, end1, rad1, end2, rad2, nSubdivisions, capEnds)
  4047. float end1[3], end2[3];
  4048. float rad1, rad2;
  4049. ObjPtr picture;
  4050. int nSubdivisions;
  4051. Bool capEnds;
  4052. #endif
  4053. /*Converts a frustum onto a picture*/
  4054. {
  4055.     float a[3];        /*Axial unit vector*/
  4056.     float r[MAXCYLSIDES][3];
  4057.     float s[3], n[3], f[3];
  4058.     Vertex v[MAXCYLSIDES + 1];
  4059.     double length;    /*Length of cylinder*/
  4060.     double nf;        /*Normalization factor*/
  4061.             /*Radial units around cylinder*/
  4062.     int end;        /*Counter for which end*/
  4063.     int b;        /*Counter around radius*/
  4064.     int d;        /*Delta for subdivision*/
  4065.     int k;        /*Random counter*/
  4066.     RectMeshPtr rectMesh;
  4067.     VertexPtr vertex;
  4068.  
  4069.     curNSides = 4;
  4070.     while (nSubdivisions--) curNSides *= 2;
  4071.  
  4072.     if (end2[0] == end1[0] &&
  4073.     end2[1] == end1[1] &&
  4074.     end2[2] == end1[2])
  4075.     {
  4076.     /*can't do it*/
  4077.     return;
  4078.     }
  4079.  
  4080.     /*First make an axial unit vector*/
  4081.     a[0] = end2[0] -
  4082.        end1[0];
  4083.     a[1] = end2[1] -
  4084.        end1[1];
  4085.     a[2] = end2[2] -
  4086.        end1[2];
  4087.     length = sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]);
  4088.     nf = 1.0 / length;
  4089.     a[0] *= nf; a[1] *= nf; a[2] *= nf;
  4090.  
  4091.     /*See if it's nearly colinear with i*/
  4092.     if (ABS(a[0]) > 0.8)
  4093.     {
  4094.     /*It is, so cross by j to get first r*/
  4095.     r[0][0] = -a[2];
  4096.     r[0][1] = 0.0;
  4097.     r[0][2] = a[0];
  4098.     }
  4099.     else
  4100.     {
  4101.     /*It isn't, so cross by i to get first r*/
  4102.     r[0][0] = 0.0;
  4103.     r[0][1] = a[2];
  4104.     r[0][2] = -a[1];
  4105.     }
  4106.     
  4107.     /*Normalize r*/
  4108.     length = sqrt(r[0][0]*r[0][0] + r[0][1]*r[0][1] + r[0][2]*r[0][2]);
  4109.     nf = 1.0 / length;
  4110.     r[0][0] *= nf; r[0][1] *= nf, r[0][2] *= nf;
  4111.  
  4112.     /*Cross a with first radial unit to get orthogonal unit*/
  4113.     CROSS(a, r[0], r[curNSides / 4]);
  4114.  
  4115.     /*Fill out point radii 3 and 4 by reversing 1 and 2*/
  4116.     r[curNSides / 2][0] = -r[0][0];
  4117.     r[curNSides / 2][1] = -r[0][1];
  4118.     r[curNSides / 2][2] = -r[0][2];
  4119.  
  4120.     r[curNSides / 4 * 3][0] = -r[curNSides / 4][0];
  4121.     r[curNSides / 4 * 3][1] = -r[curNSides / 4][1];
  4122.     r[curNSides / 4 * 3][2] = -r[curNSides / 4][2];
  4123.  
  4124.     /*Subdivide the sides of the cylinder*/
  4125.     k = 0;
  4126.     for (d = curNSides / 4; d > 1; d /= 2)
  4127.     {
  4128.     register double cef_2;    /*Chord extension factor/2*/
  4129.     
  4130.     cef_2 = cefs_2[k];
  4131.     ++k;
  4132.     
  4133.     for (b = 0; b < curNSides; b += d)
  4134.     {
  4135.         register int m, e;    /*Midpoint and endpoint*/
  4136.  
  4137.         /*Interpolate center of chord*/
  4138.         e = (b + d) & (curNSides - 1);    /*Clip circular*/
  4139.         m = b + d / 2;
  4140.         r[m][0] = (r[b][0] + r[e][0]) * cef_2;
  4141.         r[m][1] = (r[b][1] + r[e][1]) * cef_2;
  4142.         r[m][2] = (r[b][2] + r[e][2]) * cef_2;
  4143.     }
  4144.     }
  4145.  
  4146.     /*Convert the cylinder*/
  4147.     rectMesh = AppendRectMeshToPicture(picture, 2, curNSides + 1, false);
  4148.  
  4149.     f[0] = rad2 * r[curNSides - 1][0] + end2[0] - 
  4150.        (rad1 * r[curNSides - 1][0] + end1[0]);
  4151.     f[1] = rad2 * r[curNSides - 1][1] + end2[1] - 
  4152.        (rad1 * r[curNSides - 1][1] + end1[1]);
  4153.     f[2] = rad2 * r[curNSides - 1][2] + end2[2] - 
  4154.        (rad1 * r[curNSides - 1][2] + end1[2]);
  4155.     CROSS(f, r[curNSides - 1], s);
  4156.     CROSS(s, f, n);
  4157.     NORMALIZE(n);
  4158.  
  4159.     vertex = RectMeshVertex(rectMesh, 0, 0);
  4160.     vertex -> position[0] = rad2 * r[curNSides - 1][0] + end2[0];
  4161.     vertex -> position[1] = rad2 * r[curNSides - 1][1] + end2[1];
  4162.     vertex -> position[2] = rad2 * r[curNSides - 1][2] + end2[2];
  4163.  
  4164. #if 0
  4165.     vertex -> normal[0] = r[curNSides - 1][0];
  4166.     vertex -> normal[1] = r[curNSides - 1][1];
  4167.     vertex -> normal[2] = r[curNSides - 1][2];
  4168. #else
  4169.     vertex -> normal[0] = n[0];
  4170.     vertex -> normal[1] = n[1];
  4171.     vertex -> normal[2] = n[2];
  4172. #endif
  4173.  
  4174.     vertex = RectMeshVertex(rectMesh, 1, 0);
  4175.     vertex -> position[0] = rad1 * r[curNSides - 1][0] + end1[0];
  4176.     vertex -> position[1] = rad1 * r[curNSides - 1][1] + end1[1];
  4177.     vertex -> position[2] = rad1 * r[curNSides - 1][2] + end1[2];
  4178.  
  4179. #if 0
  4180.     vertex -> normal[0] = r[curNSides - 1][0];
  4181.     vertex -> normal[1] = r[curNSides - 1][1];
  4182.     vertex -> normal[2] = r[curNSides - 1][2];
  4183. #else
  4184.     vertex -> normal[0] = n[0];
  4185.     vertex -> normal[1] = n[1];
  4186.     vertex -> normal[2] = n[2];
  4187. #endif
  4188.  
  4189.     for (k = 0; k < curNSides; ++k)
  4190.     {
  4191.     f[0] = rad2 * r[k][0] + end2[0] - 
  4192.            (rad1 * r[k][0] + end1[0]);
  4193.     f[1] = rad2 * r[k][1] + end2[1] - 
  4194.            (rad1 * r[k][1] + end1[1]);
  4195.     f[2] = rad2 * r[k][2] + end2[2] - 
  4196.            (rad1 * r[k][2] + end1[2]);
  4197.     CROSS(f, r[k], s);
  4198.     CROSS(s, f, n);
  4199.     NORMALIZE(n);
  4200.  
  4201.     vertex = RectMeshVertex(rectMesh, 0, k + 1);    
  4202.     vertex -> position[0] = rad2 * r[k][0] + end2[0];
  4203.     vertex -> position[1] = rad2 * r[k][1] + end2[1];
  4204.     vertex -> position[2] = rad2 * r[k][2] + end2[2];
  4205.  
  4206. #if 0
  4207.     vertex -> normal[0] = r[k][0];
  4208.     vertex -> normal[1] = r[k][1];
  4209.     vertex -> normal[2] = r[k][2];
  4210. #else
  4211.     vertex -> normal[0] = n[0];
  4212.     vertex -> normal[1] = n[1];
  4213.     vertex -> normal[2] = n[2];
  4214. #endif
  4215.  
  4216.     vertex = RectMeshVertex(rectMesh, 1, k + 1);    
  4217.     vertex -> position[0] = rad1 * r[k][0] + end1[0];
  4218.     vertex -> position[1] = rad1 * r[k][1] + end1[1];
  4219.     vertex -> position[2] = rad1 * r[k][2] + end1[2];
  4220.  
  4221. #if 0
  4222.     vertex -> normal[0] = r[k][0];
  4223.     vertex -> normal[1] = r[k][1];
  4224.     vertex -> normal[2] = r[k][2];
  4225. #else
  4226.     vertex -> normal[0] = n[0];
  4227.     vertex -> normal[1] = n[1];
  4228.     vertex -> normal[2] = n[2];
  4229. #endif
  4230.     }
  4231.  
  4232.     InterpRectCenters(rectMesh);
  4233.  
  4234.     if (capEnds)
  4235.     {
  4236.     /*Do top cap*/
  4237.     for (k = 0; k < curNSides; ++k)
  4238.     {
  4239.         v[k] . position[0] = rad2 * r[k][0] + end2[0];
  4240.         v[k] . position[1] = rad2 * r[k][1] + end2[1];
  4241.         v[k] . position[2] = rad2 * r[k][2] + end2[2];
  4242.         v[k] . normal[0] = a[0];
  4243.         v[k] . normal[1] = a[1];
  4244.         v[k] . normal[2] = a[2];
  4245.     }
  4246.     AppendPolyToPicture(picture, curNSides, v);
  4247.     
  4248.     /*Do bottom cap*/
  4249.     for (k = 0; k < curNSides; ++k)
  4250.     {
  4251.         v[k] . position[0] = rad1 * r[k][0] + end1[0];
  4252.         v[k] . position[1] = rad1 * r[k][1] + end1[1];
  4253.         v[k] . position[2] = rad1 * r[k][2] + end1[2];
  4254.         v[k] . normal[0] = -a[0];
  4255.         v[k] . normal[1] = -a[1];
  4256.         v[k] . normal[2] = -a[2];
  4257.     }
  4258.     AppendPolyToPicture(picture, curNSides, v);
  4259.     }
  4260. }
  4261.  
  4262. #ifdef PROTO
  4263. PicItemPtr ColorItemsByItems(PicItemPtr destItem, ObjPtr owner, PicItemPtr curItem)
  4264. #else
  4265. PicItemPtr ColorItemsByItems(dest, owner, curItem)
  4266. ObjPtr dest, pic;
  4267. ObjPtr owner;
  4268. PicItemPtr curItem;
  4269. #endif
  4270. /*Colors a picture with another picture, which must be the source picture*/
  4271. {
  4272.     ObjPtr var;
  4273.     Bool capEnds;
  4274.  
  4275.     capEnds = GetPredicate(owner, CAPENDSP);
  4276.  
  4277.     while (curItem)
  4278.     {
  4279.     if (!destItem)
  4280.     {
  4281.         ReportError("ColorItemsByItems", "Pictures don't match");
  4282.         break;
  4283.     }
  4284.     switch (curItem -> type)
  4285.     {
  4286.         case POLYGON:
  4287.         case PLANARPOLYGON:
  4288.         case POLYLINE:
  4289.         ColorItemWithIndex(destItem, 
  4290.             ((PolyPtr) curItem) -> vertices[0] -> colorIndex);
  4291.         break;
  4292.         case FRUSTUM:
  4293.  
  4294.         ColorItemWithIndex(destItem,
  4295.             ((FrustumPtr) curItem) -> colorIndex);
  4296.         if (capEnds)
  4297.         {
  4298.             /*Cap the ends*/
  4299.             destItem = destItem -> next;
  4300.             if (!destItem) break;
  4301.             ColorItemWithIndex(destItem,
  4302.             ((FrustumPtr) curItem) -> colorIndex);
  4303.             destItem = destItem -> next;
  4304.             if (!destItem) break;
  4305.             ColorItemWithIndex(destItem,
  4306.             ((FrustumPtr) curItem) -> colorIndex);
  4307.         }
  4308.         break;
  4309.         case SPHERE:
  4310.  
  4311.         ColorItemWithIndex(destItem,
  4312.             ((SpherePtr) curItem) -> centerVertex -> colorIndex);
  4313.         break;
  4314.         case POLYGONS:
  4315.  
  4316.         {
  4317.             PolyPtr polygons;
  4318.             polygons = ((PolysPtr) curItem) -> polygons;
  4319.             if (polygons)
  4320.             {
  4321.             ColorItemWithIndex((PicItemPtr) polygons,
  4322.                 polygons -> vertices[0] -> colorIndex);
  4323.             }
  4324.         }
  4325.         break;
  4326.         case RECTMESH:
  4327.  
  4328.         ColorItemWithIndex(destItem,
  4329.             ((RectMeshPtr) curItem) -> vertices[0] -> colorIndex);
  4330.         break;
  4331.  
  4332.     }
  4333.     curItem = curItem -> next;
  4334.     destItem = destItem -> next;
  4335.     }
  4336.     return destItem;
  4337. }
  4338.  
  4339. #ifdef PROTO
  4340. void ColorPictureByPicture(ObjPtr dest, ObjPtr owner, ObjPtr pic)
  4341. #else
  4342. void ColorPictureByPicture(dest, owner, pic)
  4343. ObjPtr dest, pic;
  4344. ObjPtr owner;
  4345. #endif
  4346. /*Colors a picture with another picture, which must be the source picture*/
  4347. {
  4348.     PicItemPtr curItem, destItem;
  4349.  
  4350.     curItem = ((PicPtr) pic) -> items;
  4351.     destItem = ((PicPtr) dest) -> items;
  4352.     ColorItemsByItems(destItem, owner, curItem);
  4353. }
  4354.  
  4355. #ifdef PROTO
  4356. ObjPtr ConvertOntoPicture(ObjPtr retVal, ObjPtr pic, ObjPtr owner)
  4357. #else
  4358. ObjPtr ConvertOntoPicture(retVal, pic, owner)
  4359. ObjPtr retVal;
  4360. ObjPtr pic;
  4361. ObjPtr owner;
  4362. #endif
  4363. /*Returns a copy of pic converted into internal form on the end of retVal.  
  4364.   Owner can give info on conversion*/
  4365. {
  4366.     PicItemPtr curItem;
  4367.     ObjPtr var;
  4368.     int sphereSub;
  4369.     int frustumSub;
  4370.     Bool capEnds;
  4371.  
  4372.     var = GetIntVar("ConvertOntoPicture", owner, SPHERESUBDIV);
  4373.     if (var)
  4374.     {
  4375.     sphereSub = GetInt(var);
  4376.     }
  4377.     else
  4378.     {
  4379.     sphereSub = 2;
  4380.     }
  4381.  
  4382.     var = GetIntVar("ConvertOntoPicture", owner, FRUSTUMSUBDIV);
  4383.     if (var)
  4384.     {
  4385.     frustumSub = GetInt(var);
  4386.     }
  4387.     else
  4388.     {
  4389.     frustumSub = 2;
  4390.     }
  4391.  
  4392.     capEnds = GetPredicate(owner, CAPENDSP);
  4393.  
  4394.     curItem = ((PicPtr) pic) -> items;
  4395.     while(curItem)
  4396.     {
  4397.     switch (curItem -> type)
  4398.     {
  4399.         case POLYGON:
  4400.         case PLANARPOLYGON:
  4401.         ConvertPolyOntoPicture(retVal, (PolyPtr) curItem);
  4402.         break;
  4403.         case POLYLINE:
  4404.         ConvertPolyOntoPicture(retVal, (PolyPtr) curItem);
  4405.         break;
  4406.         case FRUSTUM:
  4407.         ConvertFrustumOntoPicture(retVal, 
  4408.             ((FrustumPtr) curItem) -> end1,
  4409.             ((FrustumPtr) curItem) -> rad1,
  4410.             ((FrustumPtr) curItem) -> end2,
  4411.             ((FrustumPtr) curItem) -> rad2,
  4412.             frustumSub, capEnds);
  4413.         break;
  4414.         case SPHERE:
  4415.         ConvertSphereOntoPicture(retVal,
  4416.             ((SpherePtr) curItem) -> centerVertex,
  4417.             ((SpherePtr) curItem) -> radius,
  4418.             0,
  4419.             sphereSub);
  4420.         break;
  4421.         case POLYGONS:
  4422.         {
  4423.             PolyPtr polygons;
  4424.             PolysPtr polySet;
  4425.             polySet = AppendPolysToPicture(retVal);
  4426.             polygons = ((PolysPtr) curItem) -> polygons;
  4427.             while (polygons)
  4428.             {
  4429.             ConvertPolyOntoPolys(polySet, polygons);
  4430.             polygons = (PolyPtr) (polygons -> item . next);
  4431.             }
  4432.         }
  4433.         break;
  4434.         case RECTMESH:
  4435.         {
  4436.             RectMeshPtr rectMesh;
  4437.             long k;
  4438.             rectMesh = AppendRectMeshToPicture(retVal,
  4439.             ((RectMeshPtr) curItem) -> xDim, 
  4440.             ((RectMeshPtr) curItem) -> yDim,
  4441.             ((RectMeshPtr) curItem) -> inCenter);
  4442.             for (k = 0; k < (((RectMeshPtr) curItem) -> xDim * (2 * ((RectMeshPtr) curItem) -> yDim - 1)); ++k)
  4443.             {
  4444.             ((RectMeshPtr) rectMesh) -> vertices[k] -> normal[0] =
  4445.             ((RectMeshPtr) curItem) -> vertices[k] -> normal[0];
  4446.             ((RectMeshPtr) rectMesh) -> vertices[k] -> normal[1] =
  4447.             ((RectMeshPtr) curItem) -> vertices[k] -> normal[1];
  4448.             ((RectMeshPtr) rectMesh) -> vertices[k] -> normal[2] =
  4449.             ((RectMeshPtr) curItem) -> vertices[k] -> normal[2];
  4450.             ((RectMeshPtr) rectMesh) -> vertices[k] -> position[0] =
  4451.             ((RectMeshPtr) curItem) -> vertices[k] -> position[0];
  4452.             ((RectMeshPtr) rectMesh) -> vertices[k] -> position[1] =
  4453.             ((RectMeshPtr) curItem) -> vertices[k] -> position[1];
  4454.             ((RectMeshPtr) rectMesh) -> vertices[k] -> position[2] =
  4455.             ((RectMeshPtr) curItem) -> vertices[k] -> position[2];
  4456.             ((RectMeshPtr) rectMesh) -> vertices[k] -> colorIndex =
  4457.             ((RectMeshPtr) curItem) -> vertices[k] -> colorIndex;
  4458.             }
  4459.         }
  4460.         break;
  4461.     }
  4462.     curItem = curItem -> next;
  4463.     }
  4464.     return retVal;
  4465. }
  4466.  
  4467. #ifdef PROTO
  4468. ObjPtr ConvertPicture(ObjPtr pic, ObjPtr owner)
  4469. #else
  4470. ObjPtr ConvertPicture(pic, owner)
  4471. ObjPtr pic;
  4472. ObjPtr owner;
  4473. #endif
  4474. /*Returns a copy of pic converted into internal form.  Owner can give info on conversion*/
  4475. {
  4476.     ObjPtr retVal;
  4477.     retVal = NewPicture();
  4478.     ConvertOntoPicture(retVal, pic, owner);
  4479.     return retVal;
  4480. }
  4481.  
  4482. void GetPictureBounds(pic, bounds)
  4483. ObjPtr pic;
  4484. real bounds[6];
  4485. /*Returns the bounds of pic in bounds*/
  4486. {
  4487.     PicItemPtr curItem;
  4488.     bounds[0] = bounds[2] = bounds[4] = PLUSINF;
  4489.     bounds[1] = bounds[3] = bounds[5] = MINUSINF;
  4490.  
  4491.     curItem = ((PicPtr) pic) -> items;
  4492.  
  4493.     while (curItem)
  4494.     {
  4495.     switch(curItem -> type)
  4496.     {
  4497.         case SPHERE:
  4498.         if (((SpherePtr) curItem) -> centerVertex -> position[0] -
  4499.             ((SpherePtr) curItem) -> radius < bounds[0])
  4500.         {
  4501.             bounds[0] = ((SpherePtr) curItem) -> centerVertex -> position[0] -
  4502.                 ((SpherePtr) curItem) -> radius;
  4503.         }
  4504.         if (((SpherePtr) curItem) -> centerVertex -> position[0] +
  4505.             ((SpherePtr) curItem) -> radius > bounds[1])
  4506.         {
  4507.             bounds[1] = ((SpherePtr) curItem) -> centerVertex -> position[0] +
  4508.                 ((SpherePtr) curItem) -> radius;
  4509.         }
  4510.         if (((SpherePtr) curItem) -> centerVertex -> position[1] -
  4511.             ((SpherePtr) curItem) -> radius < bounds[2])
  4512.         {
  4513.             bounds[2] = ((SpherePtr) curItem) -> centerVertex -> position[1] -
  4514.                 ((SpherePtr) curItem) -> radius;
  4515.         }
  4516.         if (((SpherePtr) curItem) -> centerVertex -> position[1] +
  4517.             ((SpherePtr) curItem) -> radius > bounds[3])
  4518.         {
  4519.             bounds[3] = ((SpherePtr) curItem) -> centerVertex -> position[1] +
  4520.                 ((SpherePtr) curItem) -> radius;
  4521.         }
  4522.         if (((SpherePtr) curItem) -> centerVertex -> position[2] -
  4523.             ((SpherePtr) curItem) -> radius < bounds[4])
  4524.         {
  4525.             bounds[4] = ((SpherePtr) curItem) -> centerVertex -> position[2] -
  4526.                 ((SpherePtr) curItem) -> radius;
  4527.         }
  4528.         if (((SpherePtr) curItem) -> centerVertex -> position[2] +
  4529.             ((SpherePtr) curItem) -> radius > bounds[5])
  4530.         {
  4531.             bounds[5] = ((SpherePtr) curItem) -> centerVertex -> position[2] +
  4532.                 ((SpherePtr) curItem) -> radius;
  4533.         }
  4534.         break;
  4535.         case FRUSTUM:
  4536.         if (((FrustumPtr) curItem) -> end1[0] - 
  4537.             ((FrustumPtr) curItem) -> rad1 < bounds[0])
  4538.         {
  4539.             bounds[0] = ((FrustumPtr) curItem) -> end1[0] - 
  4540.                     ((FrustumPtr) curItem) -> rad1;
  4541.         }
  4542.         if (((FrustumPtr) curItem) -> end1[0] + 
  4543.             ((FrustumPtr) curItem) -> rad1 > bounds[1])
  4544.         {
  4545.             bounds[1] = ((FrustumPtr) curItem) -> end1[0] + 
  4546.                     ((FrustumPtr) curItem) -> rad1;
  4547.         }
  4548.         if (((FrustumPtr) curItem) -> end1[1] - 
  4549.             ((FrustumPtr) curItem) -> rad1 < bounds[2])
  4550.         {
  4551.             bounds[2] = ((FrustumPtr) curItem) -> end1[1] - 
  4552.                     ((FrustumPtr) curItem) -> rad1;
  4553.         }
  4554.         if (((FrustumPtr) curItem) -> end1[1] + 
  4555.             ((FrustumPtr) curItem) -> rad1 > bounds[3])
  4556.         {
  4557.             bounds[3] = ((FrustumPtr) curItem) -> end1[1] + 
  4558.                     ((FrustumPtr) curItem) -> rad1;
  4559.         }
  4560.         if (((FrustumPtr) curItem) -> end1[2] - 
  4561.             ((FrustumPtr) curItem) -> rad1 < bounds[4])
  4562.         {
  4563.             bounds[4] = ((FrustumPtr) curItem) -> end1[2] - 
  4564.                     ((FrustumPtr) curItem) -> rad1;
  4565.         }
  4566.         if (((FrustumPtr) curItem) -> end1[2] + 
  4567.             ((FrustumPtr) curItem) -> rad1 > bounds[5])
  4568.         {
  4569.             bounds[5] = ((FrustumPtr) curItem) -> end1[2] + 
  4570.                     ((FrustumPtr) curItem) -> rad1;
  4571.         }
  4572.  
  4573.         if (((FrustumPtr) curItem) -> end2[0] - 
  4574.             ((FrustumPtr) curItem) -> rad2 < bounds[0])
  4575.         {
  4576.             bounds[0] = ((FrustumPtr) curItem) -> end2[0] - 
  4577.                     ((FrustumPtr) curItem) -> rad2;
  4578.         }
  4579.         if (((FrustumPtr) curItem) -> end2[0] + 
  4580.             ((FrustumPtr) curItem) -> rad2 > bounds[1])
  4581.         {
  4582.             bounds[1] = ((FrustumPtr) curItem) -> end2[0] + 
  4583.                     ((FrustumPtr) curItem) -> rad2;
  4584.         }
  4585.         if (((FrustumPtr) curItem) -> end2[1] - 
  4586.             ((FrustumPtr) curItem) -> rad2 < bounds[2])
  4587.         {
  4588.             bounds[2] = ((FrustumPtr) curItem) -> end2[1] - 
  4589.                     ((FrustumPtr) curItem) -> rad2;
  4590.         }
  4591.         if (((FrustumPtr) curItem) -> end2[1] + 
  4592.             ((FrustumPtr) curItem) -> rad2 > bounds[3])
  4593.         {
  4594.             bounds[3] = ((FrustumPtr) curItem) -> end2[1] + 
  4595.                     ((FrustumPtr) curItem) -> rad2;
  4596.         }
  4597.         if (((FrustumPtr) curItem) -> end2[2] - 
  4598.             ((FrustumPtr) curItem) -> rad2 < bounds[4])
  4599.         {
  4600.             bounds[4] = ((FrustumPtr) curItem) -> end2[2] - 
  4601.                     ((FrustumPtr) curItem) -> rad2;
  4602.         }
  4603.         if (((FrustumPtr) curItem) -> end2[2] + 
  4604.             ((FrustumPtr) curItem) -> rad2 > bounds[5])
  4605.         {
  4606.             bounds[5] = ((FrustumPtr) curItem) -> end2[2] + 
  4607.                     ((FrustumPtr) curItem) -> rad2;
  4608.         }
  4609.         break;
  4610.         case POLYGON:
  4611.         case PLANARPOLYGON:
  4612.         case POLYLINE:
  4613.         {
  4614.             int k;
  4615.             VertexPtr *curVertex;
  4616.  
  4617.             curVertex = ((PolyPtr) curItem) -> vertices;
  4618.             for (k = 0; k < ((PolyPtr) curItem) -> nVertices; ++k)
  4619.             {
  4620.             if ((*curVertex) -> position[0] < bounds[0])
  4621.             {
  4622.                 bounds[0] = (*curVertex) -> position[0];
  4623.             }
  4624.             if ((*curVertex) -> position[0] > bounds[1])
  4625.             {
  4626.                 bounds[1] = (*curVertex) -> position[0];
  4627.             }
  4628.             if ((*curVertex) -> position[1] < bounds[2])
  4629.             {
  4630.                 bounds[2] = (*curVertex) -> position[1];
  4631.             }
  4632.             if ((*curVertex) -> position[1] > bounds[3])
  4633.             {
  4634.                 bounds[3] = (*curVertex) -> position[1];
  4635.             }
  4636.             if ((*curVertex) -> position[2] < bounds[4])
  4637.             {
  4638.                 bounds[4] = (*curVertex) -> position[2];
  4639.             }
  4640.             if ((*curVertex) -> position[2] > bounds[5])
  4641.             {
  4642.                 bounds[5] = (*curVertex) -> position[2];
  4643.             }
  4644.             ++curVertex;
  4645.             }
  4646.         }
  4647.         break;
  4648.         case POLYGONS:
  4649.         {
  4650.             PolyPtr polygons;
  4651.             polygons = ((PolysPtr) curItem) -> polygons;
  4652.             while (polygons)
  4653.             {
  4654.             int k;
  4655.             VertexPtr *curVertex;
  4656.  
  4657.             curVertex = polygons -> vertices;
  4658.             for (k = 0; k < polygons -> nVertices; ++k)
  4659.             {
  4660.                 if ((*curVertex) -> position[0] < bounds[0])
  4661.                 {
  4662.                 bounds[0] = (*curVertex) -> position[0];
  4663.                 }
  4664.                 if ((*curVertex) -> position[0] > bounds[1])
  4665.                 {
  4666.                 bounds[1] = (*curVertex) -> position[0];
  4667.                 }
  4668.                 if ((*curVertex) -> position[1] < bounds[2])
  4669.                 {
  4670.                 bounds[2] = (*curVertex) -> position[1];
  4671.                 }
  4672.                 if ((*curVertex) -> position[1] > bounds[3])
  4673.                 {
  4674.                 bounds[3] = (*curVertex) -> position[1];
  4675.                 }
  4676.                 if ((*curVertex) -> position[2] < bounds[4])
  4677.                 {
  4678.                 bounds[4] = (*curVertex) -> position[2];
  4679.                 }
  4680.                 if ((*curVertex) -> position[2] > bounds[5])
  4681.                 {
  4682.                 bounds[5] = (*curVertex) -> position[2];
  4683.                 }
  4684.                 ++curVertex;
  4685.             }
  4686.             polygons = (PolyPtr) (polygons -> item . next);
  4687.             }
  4688.         }
  4689.         break;
  4690.         case RECTMESH:
  4691.         {
  4692.             register long i, j, offset;
  4693.             VertexPtr *vertices;
  4694.  
  4695.             vertices = ((RectMeshPtr) curItem) -> vertices;
  4696.  
  4697.             for (i = 0; i < ((RectMeshPtr) curItem) -> xDim; ++i)
  4698.             {
  4699.             for (j = 0; j < ((RectMeshPtr) curItem) -> yDim; ++j)
  4700.             {
  4701.                 offset = RECTMESHVERTEX((RectMeshPtr) curItem, i, j);
  4702.                 if (vertices[offset] -> position[0] < bounds[0])
  4703.                 {
  4704.                 bounds[0] = vertices[offset] -> position[0];
  4705.                 }
  4706.                 if (vertices[offset] -> position[0] > bounds[1])
  4707.                 {
  4708.                 bounds[1] = vertices[offset] -> position[0];
  4709.                 }
  4710.                 if (vertices[offset] -> position[1] < bounds[2])
  4711.                 {
  4712.                 bounds[2] = vertices[offset] -> position[1];
  4713.                 }
  4714.                 if (vertices[offset] -> position[1] > bounds[3])
  4715.                 {
  4716.                 bounds[3] = vertices[offset] -> position[1];
  4717.                 }
  4718.                 if (vertices[offset] -> position[2] < bounds[4])
  4719.                 {
  4720.                 bounds[4] = vertices[offset] -> position[2];
  4721.                 }
  4722.                 if (vertices[offset] -> position[2] > bounds[5])
  4723.                 {
  4724.                 bounds[5] = vertices[offset] -> position[2];
  4725.                 }
  4726.             }
  4727.             }
  4728.         }
  4729.         break;
  4730.     }
  4731.     curItem = curItem -> next;
  4732.     }
  4733. }
  4734.  
  4735. #ifdef PROTO
  4736. void OpenGraphObj(ObjPtr object)
  4737. #else
  4738. ObjPtr OpenGraphObj(object)
  4739. ObjPtr object;
  4740. #endif
  4741. /*Opens an existing graphical object*/
  4742. {
  4743. #ifdef GRAPHICS
  4744. #ifdef GRAPHOBJ
  4745.     makeobj(GetInt(object));
  4746. #endif
  4747. #endif
  4748. }
  4749.  
  4750. #ifdef PROTO
  4751. void CloseGraphObj(ObjPtr object)
  4752. #else
  4753. void CloseGraphObj(object)
  4754. ObjPtr object;
  4755. #endif
  4756. /*Closes a graphical object*/
  4757. {
  4758. #ifdef GRAPHICS
  4759. #ifdef GRAPHOBJ
  4760.     closeobj();
  4761. #endif
  4762. #endif
  4763. }
  4764.  
  4765. #ifdef PROTO
  4766. void DrawGraphObj(ObjPtr object)
  4767. #else
  4768. void DrawGraphObj(object)
  4769. ObjPtr object;
  4770. #endif
  4771. /*Draw a graphical object*/
  4772. {
  4773. #ifdef GRAPHICS
  4774. #ifdef GRAPHOBJ
  4775.     callobj(GetInt(object));
  4776. #endif
  4777. #endif
  4778. }
  4779.  
  4780. #ifdef GRAPHICS
  4781. #ifdef GRAPHOBJ
  4782. static ObjPtr CleanupGraphObj(object)
  4783. ObjPtr object;
  4784. /*Cleans up a graphical object*/
  4785. {
  4786.     delobj(GetInt(object));
  4787.     return ObjTrue;
  4788. }
  4789. #endif
  4790. #endif
  4791.  
  4792. #ifdef PROTO
  4793. ObjPtr NewOpenGraphObj(void)
  4794. #else
  4795. ObjPtr NewOpenGraphObj()
  4796. #endif
  4797. /*Returns a pointer to a new, opened graphical object.
  4798. */
  4799. {
  4800. #ifdef GRAPHICS
  4801. #ifdef GRAPHOBJ
  4802.     Object obj;
  4803.     ObjPtr retVal;
  4804.  
  4805.     obj = genobj();
  4806.  
  4807.     retVal = NewInt(obj);
  4808.     SetMethod(retVal, CLEANUP, CleanupGraphObj);
  4809.     OpenGraphObj(retVal);
  4810.     return retVal;
  4811. #endif
  4812. #endif
  4813. }
  4814.